From 4b69dcb1caf590e0edf20c601bf7afc0a9342b58 Mon Sep 17 00:00:00 2001 From: terrafrost Date: Sun, 10 Apr 2016 11:25:31 -0500 Subject: [PATCH] Revert "Merge remote-tracking branch 'bantu/bootstrap'" This reverts commit ef04c870e93128e7bd5e4445c8521380ae6ff6ce, reversing changes made to cd57bf31ae576a178016209576c8a3c305c7b82f. --- .gitattributes | 8 - .travis.yml | 15 +- AUTHORS | 1 - CHANGELOG.md | 53 +- LICENSE | 2 +- README.md | 10 +- composer.json | 10 +- composer.lock | 682 +++--- phpseclib/Crypt/AES.php | 57 +- phpseclib/Crypt/Base.php | 486 ++-- phpseclib/Crypt/Blowfish.php | 94 +- phpseclib/Crypt/DES.php | 137 +- phpseclib/Crypt/Hash.php | 657 ++++-- phpseclib/Crypt/RC2.php | 159 +- phpseclib/Crypt/RC4.php | 115 +- phpseclib/Crypt/RSA.php | 2075 +++++++++++------ phpseclib/Crypt/RSA/MSBLOB.php | 223 -- phpseclib/Crypt/RSA/OpenSSH.php | 140 -- phpseclib/Crypt/RSA/PKCS.php | 485 ---- phpseclib/Crypt/RSA/PKCS1.php | 172 -- phpseclib/Crypt/RSA/PKCS8.php | 208 -- phpseclib/Crypt/RSA/PuTTY.php | 311 --- phpseclib/Crypt/RSA/Raw.php | 103 - phpseclib/Crypt/RSA/XML.php | 146 -- phpseclib/Crypt/Random.php | 120 +- phpseclib/Crypt/Rijndael.php | 284 ++- phpseclib/Crypt/TripleDES.php | 138 +- phpseclib/Crypt/Twofish.php | 155 +- .../Exception/BadConfigurationException.php | 26 - phpseclib/Exception/FileNotFoundException.php | 26 - .../NoSupportedAlgorithmsException.php | 26 - .../UnsupportedAlgorithmException.php | 26 - phpseclib/File/ANSI.php | 52 +- phpseclib/File/ASN1.php | 91 +- phpseclib/File/ASN1/Element.php | 4 +- phpseclib/File/X509.php | 537 ++--- phpseclib/Math/BigInteger.php | 848 +++---- phpseclib/Net/SCP.php | 51 +- phpseclib/Net/SFTP.php | 570 +++-- phpseclib/Net/SFTP/Stream.php | 159 +- phpseclib/Net/SSH1.php | 348 +-- phpseclib/Net/SSH2.php | 1015 ++++---- phpseclib/System/SSH/Agent.php | 32 +- phpseclib/System/SSH/Agent/Identity.php | 59 +- tests/Functional/Net/SFTPStreamTest.php | 28 - tests/Functional/Net/SFTPTestCase.php | 3 - tests/Functional/Net/SFTPUserStoryTest.php | 41 +- tests/Functional/Net/SSH2Test.php | 35 - tests/PhpseclibFunctionalTestCase.php | 2 + tests/PhpseclibTestCase.php | 8 +- tests/Unit/Crypt/AES/TestCase.php | 132 +- tests/Unit/Crypt/BlowfishTest.php | 20 +- tests/Unit/Crypt/DESTest.php | 78 + tests/Unit/Crypt/Hash/MD5Test.php | 49 + tests/Unit/Crypt/Hash/SHA256Test.php | 81 + tests/Unit/Crypt/Hash/SHA256_96Test.php | 32 + tests/Unit/Crypt/Hash/SHA512Test.php | 81 + tests/Unit/Crypt/Hash/SHA512_96Test.php | 32 + tests/Unit/Crypt/Hash/TestCase.php | 52 + tests/Unit/Crypt/HashTest.php | 423 ---- tests/Unit/Crypt/RC2Test.php | 23 +- tests/Unit/Crypt/RC4Test.php | 20 +- tests/Unit/Crypt/RSA/CreateKeyTest.php | 34 - tests/Unit/Crypt/RSA/LoadKeyTest.php | 255 +- tests/Unit/Crypt/RSA/ModeTest.php | 68 +- tests/Unit/Crypt/TripleDESTest.php | 40 +- tests/Unit/Crypt/TwofishTest.php | 3 +- tests/Unit/File/ASN1Test.php | 2 +- tests/Unit/File/X509/CSRTest.php | 25 - tests/Unit/File/X509/SPKACTest.php | 4 +- tests/Unit/File/X509/X509Test.php | 96 +- .../Math/BigInteger/InternalOpenSSLTest.php | 2 +- tests/Unit/Math/BigInteger/TestCase.php | 68 +- tests/Unit/Net/SSH2Test.php | 12 - tests/bootstrap.php | 2 +- travis/install-php-extensions.sh | 7 +- travis/run-phpunit.sh | 2 +- 77 files changed, 5404 insertions(+), 7272 deletions(-) delete mode 100644 phpseclib/Crypt/RSA/MSBLOB.php delete mode 100644 phpseclib/Crypt/RSA/OpenSSH.php delete mode 100644 phpseclib/Crypt/RSA/PKCS.php delete mode 100644 phpseclib/Crypt/RSA/PKCS1.php delete mode 100644 phpseclib/Crypt/RSA/PKCS8.php delete mode 100644 phpseclib/Crypt/RSA/PuTTY.php delete mode 100644 phpseclib/Crypt/RSA/Raw.php delete mode 100644 phpseclib/Crypt/RSA/XML.php delete mode 100644 phpseclib/Exception/BadConfigurationException.php delete mode 100644 phpseclib/Exception/FileNotFoundException.php delete mode 100644 phpseclib/Exception/NoSupportedAlgorithmsException.php delete mode 100644 phpseclib/Exception/UnsupportedAlgorithmException.php create mode 100644 tests/Unit/Crypt/DESTest.php create mode 100644 tests/Unit/Crypt/Hash/MD5Test.php create mode 100644 tests/Unit/Crypt/Hash/SHA256Test.php create mode 100644 tests/Unit/Crypt/Hash/SHA256_96Test.php create mode 100644 tests/Unit/Crypt/Hash/SHA512Test.php create mode 100644 tests/Unit/Crypt/Hash/SHA512_96Test.php create mode 100644 tests/Unit/Crypt/Hash/TestCase.php delete mode 100644 tests/Unit/Crypt/HashTest.php delete mode 100644 tests/Unit/Crypt/RSA/CreateKeyTest.php diff --git a/.gitattributes b/.gitattributes index 484960de..176a458f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,9 +1 @@ * text=auto -/build/ export-ignore -/tests/ export-ignore -/travis/ export-ignore -/.gitattributes export-ignore -/.gitignore export-ignore -/.travis.yml export-ignore -/CHANGELOG.md export-ignore -/phpunit.xml.dist export-ignore diff --git a/.travis.yml b/.travis.yml index d54c933a..3fb1d730 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,13 @@ language: php +# When adding environments here, the number of runs specified in .scrutinizer.yml +# may have to be adjusted. php: + - 5.3.3 - 5.3 - 5.4 - - 5.5.9 - 5.5 - 5.6 - - 7.0 - hhvm env: @@ -18,16 +19,10 @@ env: before_install: true install: - - wget http://ftp.gnu.org/gnu/parallel/parallel-20120522.tar.bz2 - - tar -xvjf parallel* - - cd parallel* - - ./configure - - make - - sudo make install - - cd .. + - sudo apt-get install parallel - eval `ssh-agent -s` - travis/setup-secure-shell.sh - - sh -c "if [ '$TRAVIS_PHP_VERSION' != 'hhvm' -a '$TRAVIS_PHP_VERSION' != '7.0' ]; then travis/install-php-extensions.sh; fi" + - sh -c "if [ '$TRAVIS_PHP_VERSION' != 'hhvm' ]; then travis/install-php-extensions.sh; fi" - travis/setup-composer.sh script: diff --git a/AUTHORS b/AUTHORS index a08b3099..e175f9f2 100644 --- a/AUTHORS +++ b/AUTHORS @@ -3,4 +3,3 @@ phpseclib Lead Developer: TerraFrost (Jim Wigginton) phpseclib Developers: monnerat (Patrick Monnerat) bantu (Andreas Fischer) petrich (Hans-Jürgen Petrich) - GrahamCampbell (Graham Campbell) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30c0777d..2dd2c096 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,56 +1,5 @@ # Changelog -## 2.0.1 - 2016-01-18 - -- RSA: fix regression in PSS mode ([#769](https://github.com/phpseclib/phpseclib/pull/769)) -- RSA: fix issue loading PKCS8 specific keys ([#861](https://github.com/phpseclib/phpseclib/pull/861)) -- X509: add getOID() method ([#789](https://github.com/phpseclib/phpseclib/pull/789)) -- X509: improve base64-encoded detection rules ([#855](https://github.com/phpseclib/phpseclib/pull/855)) -- SFTP: fix quirky behavior with put() ([#830](https://github.com/phpseclib/phpseclib/pull/830)) -- SFTP: fix E_NOTICE ([#883](https://github.com/phpseclib/phpseclib/pull/883)) -- SFTP/Stream: fix issue with filenames with hashes ([#901](https://github.com/phpseclib/phpseclib/pull/901)) -- SSH2: add isAuthenticated() method ([#897](https://github.com/phpseclib/phpseclib/pull/897)) -- SSH/Agent: fix possible PHP warning ([#923](https://github.com/phpseclib/phpseclib/issues/923)) -- BigInteger: add __debugInfo() magic method ([#881](https://github.com/phpseclib/phpseclib/pull/881)) -- BigInteger: fix issue with doing bitwise not on 0 -- add getBlockLength() method to symmetric ciphers - -## 2.0.0 - 2015-08-04 - -- Classes were renamed and namespaced ([#243](https://github.com/phpseclib/phpseclib/issues/243)) -- The use of an autoloader is now required (e.g. Composer) - -## 1.0.1 - 2016-01-18 - -- RSA: fix regression in PSS mode ([#769](https://github.com/phpseclib/phpseclib/pull/769)) -- RSA: fix issue loading PKCS8 specific keys ([#861](https://github.com/phpseclib/phpseclib/pull/861)) -- X509: add getOID() method ([#789](https://github.com/phpseclib/phpseclib/pull/789)) -- X509: improve base64-encoded detection rules ([#855](https://github.com/phpseclib/phpseclib/pull/855)) -- SFTP: fix quirky behavior with put() ([#830](https://github.com/phpseclib/phpseclib/pull/830)) -- SFTP: fix E_NOTICE ([#883](https://github.com/phpseclib/phpseclib/pull/883)) -- SFTP/Stream: fix issue with filenames with hashes ([#901](https://github.com/phpseclib/phpseclib/pull/901)) -- SSH2: add isAuthenticated() method ([#897](https://github.com/phpseclib/phpseclib/pull/897)) -- SSH/Agent: fix possible PHP warning ([#923](https://github.com/phpseclib/phpseclib/issues/923)) -- BigInteger: add __debugInfo() magic method ([#881](https://github.com/phpseclib/phpseclib/pull/881)) -- BigInteger: fix issue with doing bitwise not on 0 -- add getBlockLength() method to symmetric ciphers - -## 1.0.0 - 2015-08-02 - -- OpenSSL support for symmetric ciphers ([#507](https://github.com/phpseclib/phpseclib/pull/507)) -- rewritten vt100 terminal emulator (File_ANSI) ([#689](https://github.com/phpseclib/phpseclib/pull/689)) -- agent-forwarding support (System_SSH_Agent) ([#592](https://github.com/phpseclib/phpseclib/pull/592)) -- Net_SSH2 improvements - - diffie-hellman-group-exchange-sha1/sha256 support ([#714](https://github.com/phpseclib/phpseclib/pull/714)) - - window size handling updates ([#717](https://github.com/phpseclib/phpseclib/pull/717)) -- Net_SFTP improvements - - add callback support to put() ([#655](https://github.com/phpseclib/phpseclib/pull/655)) - - stat cache fixes ([#743](https://github.com/phpseclib/phpseclib/issues/743), [#730](https://github.com/phpseclib/phpseclib/issues/730), [#709](https://github.com/phpseclib/phpseclib/issues/709), [#726](https://github.com/phpseclib/phpseclib/issues/726)) -- add "none" encryption mode to Crypt_RSA ([#692](https://github.com/phpseclib/phpseclib/pull/692)) -- misc ASN.1 / X.509 parsing fixes ([#721](https://github.com/phpseclib/phpseclib/pull/721), [#627](https://github.com/phpseclib/phpseclib/pull/627)) -- use a random serial number for new X509 certs ([#740](https://github.com/phpseclib/phpseclib/pull/740)) -- add getPublicKeyFingerprint() to Crypt_RSA ([#677](https://github.com/phpseclib/phpseclib/pull/677)) - ## 0.3.10 - 2015-02-04 - simplify SSH2 window size handling ([#538](https://github.com/phpseclib/phpseclib/pull/538)) @@ -137,4 +86,4 @@ = add support for AES-128-CBC and DES-EDE3-CFB encrypted RSA private keys - add Net_SFTP::stat(), Net_SFTP::lstat() and Net_SFTP::rawlist() - logging was added to Net_SSH1 -- the license was changed to the less restrictive MIT license +- the license was changed to the less restrictive MIT license \ No newline at end of file diff --git a/LICENSE b/LICENSE index a8ec8ebd..75f6b204 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright 2007-2016 TerraFrost and other contributors +Copyright 2007-2013 TerraFrost and other contributors http://phpseclib.sourceforge.net/ Permission is hereby granted, free of charge, to any person obtaining diff --git a/README.md b/README.md index 102b97b8..3ca60d0b 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ # phpseclib - PHP Secure Communications Library -[![Build Status](https://travis-ci.org/phpseclib/phpseclib.svg?branch=master)](https://travis-ci.org/phpseclib/phpseclib) +[![Build Status](https://secure.travis-ci.org/phpseclib/phpseclib.png?branch=2.0)](http://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.1)](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.1.zip/download) +* [Download (0.3.10)](http://sourceforge.net/projects/phpseclib/files/phpseclib0.3.10.zip/download) * [Browse Git](https://github.com/phpseclib/phpseclib) -* [Code Coverage Report](http://phpseclib.bantux.org/code_coverage/master/latest/) +* [Code Coverage Report](http://phpseclib.bantux.org/code_coverage/php5/latest/) PEAR Channel PEAR Channel: [phpseclib.sourceforge.net](http://phpseclib.sourceforge.net/pear.htm) @@ -16,7 +16,7 @@ PEAR Channel: [phpseclib.sourceforge.net](http://phpseclib.sourceforge.net/pear. ## Documentation * [Documentation / Manual](http://phpseclib.sourceforge.net/) -* [API Documentation](http://phpseclib.bantux.org/api/master/) (generated by Sami) +* [API Documentation](http://phpseclib.bantux.org/api/2.0/) (generated by Sami) ## Support @@ -40,7 +40,7 @@ Dependencies are managed via Composer. 2. Install Dependencies ``` sh - php composer.phar install + php composer.phar install --dev ``` ## Contributing diff --git a/composer.json b/composer.json index da2e1c22..fe695fe4 100644 --- a/composer.json +++ b/composer.json @@ -43,15 +43,9 @@ "name": "Hans-Jürgen Petrich", "email": "petrich@tronic-media.com", "role": "Developer" - }, - { - "name": "Graham Campbell", - "email": "graham@alt-three.com", - "role": "Developer" } ], "require": { - "paragonie/random_compat": "^1.4|^2.0", "php": ">=5.3.3" }, "require-dev": { @@ -62,10 +56,10 @@ }, "suggest": { "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.", - "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations.", - "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.", + "ext-mcrypt": "Install the Mcrypt extension in order to speed up a wide variety of cryptographic operations.", "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations." }, + "include-path": ["phpseclib/"], "autoload": { "files": [ "phpseclib/bootstrap.php" diff --git a/composer.lock b/composer.lock index 7fbfdcb1..3e6e5c49 100644 --- a/composer.lock +++ b/composer.lock @@ -4,71 +4,21 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "deb73cf7e6004dbc2550a38c4082df2d", - "content-hash": "39f9dd8d2c209ff69eebbb83e367257e", - "packages": [ - { - "name": "paragonie/random_compat", - "version": "v2.0.2", - "source": { - "type": "git", - "url": "https://github.com/paragonie/random_compat.git", - "reference": "088c04e2f261c33bed6ca5245491cfca69195ccf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/088c04e2f261c33bed6ca5245491cfca69195ccf", - "reference": "088c04e2f261c33bed6ca5245491cfca69195ccf", - "shasum": "" - }, - "require": { - "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", - "pseudorandom", - "random" - ], - "time": "2016-04-03 06:00:07" - } - ], + "hash": "98a14889a81b2d6ecbb029483e954dec", + "packages": [], "packages-dev": [ { "name": "doctrine/instantiator", - "version": "1.0.5", + "version": "1.0.4", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + "reference": "f976e5de371104877ebc89bd8fecb0019ed9c119" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/f976e5de371104877ebc89bd8fecb0019ed9c119", + "reference": "f976e5de371104877ebc89bd8fecb0019ed9c119", "shasum": "" }, "require": { @@ -79,7 +29,7 @@ "ext-pdo": "*", "ext-phar": "*", "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~2.0" + "squizlabs/php_codesniffer": "2.0.*@ALPHA" }, "type": "library", "extra": { @@ -88,8 +38,8 @@ } }, "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + "psr-0": { + "Doctrine\\Instantiator\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -109,20 +59,20 @@ "constructor", "instantiate" ], - "time": "2015-06-14 21:17:01" + "time": "2014-10-13 12:58:55" }, { "name": "michelf/php-markdown", - "version": "1.6.0", + "version": "1.4.1", "source": { "type": "git", "url": "https://github.com/michelf/php-markdown.git", - "reference": "156e56ee036505ec637d761ee62dc425d807183c" + "reference": "de9a19c7bf352d41cc99ed86c3c0ef17e87394b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/michelf/php-markdown/zipball/156e56ee036505ec637d761ee62dc425d807183c", - "reference": "156e56ee036505ec637d761ee62dc425d807183c", + "url": "https://api.github.com/repos/michelf/php-markdown/zipball/de9a19c7bf352d41cc99ed86c3c0ef17e87394b6", + "reference": "de9a19c7bf352d41cc99ed86c3c0ef17e87394b6", "shasum": "" }, "require": { @@ -147,20 +97,20 @@ { "name": "Michel Fortin", "email": "michel.fortin@michelf.ca", - "homepage": "https://michelf.ca/", + "homepage": "http://michelf.ca/", "role": "Developer" }, { "name": "John Gruber", - "homepage": "https://daringfireball.net/" + "homepage": "http://daringfireball.net/" } ], "description": "PHP Markdown", - "homepage": "https://michelf.ca/projects/php-markdown/", + "homepage": "http://michelf.ca/projects/php-markdown/", "keywords": [ "markdown" ], - "time": "2015-12-24 01:37:31" + "time": "2014-05-05 02:43:50" }, { "name": "nikic/php-parser", @@ -209,16 +159,16 @@ }, { "name": "phing/phing", - "version": "2.14.0", + "version": "2.9.1", "source": { "type": "git", "url": "https://github.com/phingofficial/phing.git", - "reference": "7dd73c83c377623def54b58121f46b4dcb35dd61" + "reference": "393edeffa8a85d43636ce0c9b4deb1ff9ac60a5c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phingofficial/phing/zipball/7dd73c83c377623def54b58121f46b4dcb35dd61", - "reference": "7dd73c83c377623def54b58121f46b4dcb35dd61", + "url": "https://api.github.com/repos/phingofficial/phing/zipball/393edeffa8a85d43636ce0c9b4deb1ff9ac60a5c", + "reference": "393edeffa8a85d43636ce0c9b4deb1ff9ac60a5c", "shasum": "" }, "require": { @@ -227,22 +177,20 @@ "require-dev": { "ext-pdo_sqlite": "*", "lastcraft/simpletest": "@dev", - "mikey179/vfsstream": "^1.6", - "pdepend/pdepend": "2.x", - "pear/archive_tar": "1.4.x", - "pear/http_request2": "dev-trunk", - "pear/net_growl": "dev-trunk", - "pear/pear-core-minimal": "1.10.1", + "pdepend/pdepend": "1.x", + "pear-pear.php.net/http_request2": "2.2.x", + "pear-pear.php.net/net_growl": "2.7.x", + "pear-pear.php.net/pear_packagefilemanager": "1.7.x", + "pear-pear.php.net/pear_packagefilemanager2": "1.0.x", + "pear-pear.php.net/xml_serializer": "0.20.x", + "pear/pear_exception": "@dev", "pear/versioncontrol_git": "@dev", - "pear/versioncontrol_svn": "~0.5", + "pear/versioncontrol_svn": "@dev", "phpdocumentor/phpdocumentor": "2.x", - "phploc/phploc": "~2.0.6", - "phpmd/phpmd": "~2.2", + "phploc/phploc": "2.x", "phpunit/phpunit": ">=3.7", - "sebastian/git": "~1.0", "sebastian/phpcpd": "2.x", - "squizlabs/php_codesniffer": "~2.2", - "symfony/yaml": "~2.7" + "squizlabs/php_codesniffer": "1.5.x" }, "suggest": { "pdepend/pdepend": "PHP version of JDepend", @@ -263,7 +211,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.14.x-dev" + "dev-master": "2.9.x-dev" } }, "autoload": { @@ -280,23 +228,23 @@ ], "authors": [ { - "name": "Michiel Rook", - "email": "mrook@php.net" + "name": "Phing Community", + "homepage": "http://www.phing.info/trac/wiki/Development/Contributors" }, { - "name": "Phing Community", - "homepage": "https://www.phing.info/trac/wiki/Development/Contributors" + "name": "Michiel Rook", + "email": "mrook@php.net" } ], "description": "PHing Is Not GNU make; it's a PHP project build system or build tool based on Apache Ant.", - "homepage": "https://www.phing.info/", + "homepage": "http://www.phing.info/", "keywords": [ "build", "phing", "task", "tool" ], - "time": "2016-03-10 21:39:23" + "time": "2014-12-03 09:18:46" }, { "name": "phpdocumentor/reflection-docblock", @@ -349,24 +297,21 @@ }, { "name": "phpspec/prophecy", - "version": "v1.6.0", + "version": "v1.3.1", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "3c91bdf81797d725b14cb62906f9a4ce44235972" + "reference": "9ca52329bcdd1500de24427542577ebf3fc2f1c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/3c91bdf81797d725b14cb62906f9a4ce44235972", - "reference": "3c91bdf81797d725b14cb62906f9a4ce44235972", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/9ca52329bcdd1500de24427542577ebf3fc2f1c9", + "reference": "9ca52329bcdd1500de24427542577ebf3fc2f1c9", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.0.2", - "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "~2.0", - "sebastian/comparator": "~1.1", - "sebastian/recursion-context": "~1.0" + "doctrine/instantiator": "~1.0,>=1.0.2", + "phpdocumentor/reflection-docblock": "~2.0" }, "require-dev": { "phpspec/phpspec": "~2.0" @@ -374,7 +319,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.5.x-dev" + "dev-master": "1.2.x-dev" } }, "autoload": { @@ -398,7 +343,7 @@ } ], "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", + "homepage": "http://phpspec.org", "keywords": [ "Double", "Dummy", @@ -407,20 +352,20 @@ "spy", "stub" ], - "time": "2016-02-15 07:46:21" + "time": "2014-11-17 16:23:49" }, { "name": "phpunit/php-code-coverage", - "version": "2.2.4", + "version": "2.0.15", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" + "reference": "34cc484af1ca149188d0d9e91412191e398e0b67" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", - "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/34cc484af1ca149188d0d9e91412191e398e0b67", + "reference": "34cc484af1ca149188d0d9e91412191e398e0b67", "shasum": "" }, "require": { @@ -428,7 +373,7 @@ "phpunit/php-file-iterator": "~1.3", "phpunit/php-text-template": "~1.2", "phpunit/php-token-stream": "~1.3", - "sebastian/environment": "^1.3.2", + "sebastian/environment": "~1.0", "sebastian/version": "~1.0" }, "require-dev": { @@ -443,7 +388,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -469,37 +414,35 @@ "testing", "xunit" ], - "time": "2015-10-06 15:47:00" + "time": "2015-01-24 10:06:35" }, { "name": "phpunit/php-file-iterator", - "version": "1.4.1", + "version": "1.3.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0" + "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0", - "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/acd690379117b042d1c8af1fafd61bde001bf6bb", + "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb", "shasum": "" }, "require": { "php": ">=5.3.3" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4.x-dev" - } - }, "autoload": { "classmap": [ - "src/" + "File/" ] }, "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], "license": [ "BSD-3-Clause" ], @@ -516,20 +459,20 @@ "filesystem", "iterator" ], - "time": "2015-06-21 13:08:43" + "time": "2013-10-10 15:34:57" }, { "name": "phpunit/php-text-template", - "version": "1.2.1", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", + "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", "shasum": "" }, "require": { @@ -538,17 +481,20 @@ "type": "library", "autoload": { "classmap": [ - "src/" + "Text/" ] }, "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", + "email": "sb@sebastian-bergmann.de", "role": "lead" } ], @@ -557,20 +503,20 @@ "keywords": [ "template" ], - "time": "2015-06-21 13:50:34" + "time": "2014-01-30 17:20:04" }, { "name": "phpunit/php-timer", - "version": "1.0.7", + "version": "1.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b" + "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3e82f4e9fc92665fafd9157568e4dcb01d014e5b", - "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/19689d4354b295ee3d8c54b4f42c3efb69cbc17c", + "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c", "shasum": "" }, "require": { @@ -579,10 +525,13 @@ "type": "library", "autoload": { "classmap": [ - "src/" + "PHP/" ] }, "notification-url": "https://packagist.org/downloads/", + "include-path": [ + "" + ], "license": [ "BSD-3-Clause" ], @@ -598,20 +547,20 @@ "keywords": [ "timer" ], - "time": "2015-06-21 08:01:12" + "time": "2013-08-02 07:42:54" }, { "name": "phpunit/php-token-stream", - "version": "1.4.8", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da" + "reference": "db32c18eba00b121c145575fcbcd4d4d24e6db74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", - "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/db32c18eba00b121c145575fcbcd4d4d24e6db74", + "reference": "db32c18eba00b121c145575fcbcd4d4d24e6db74", "shasum": "" }, "require": { @@ -647,20 +596,20 @@ "keywords": [ "tokenizer" ], - "time": "2015-09-15 10:49:45" + "time": "2015-01-17 09:51:32" }, { "name": "phpunit/phpunit", - "version": "4.8.24", + "version": "4.5.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "a1066c562c52900a142a0e2bbf0582994671385e" + "reference": "5b578d3865a9128b9c209b011fda6539ec06e7a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a1066c562c52900a142a0e2bbf0582994671385e", - "reference": "a1066c562c52900a142a0e2bbf0582994671385e", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/5b578d3865a9128b9c209b011fda6539ec06e7a5", + "reference": "5b578d3865a9128b9c209b011fda6539ec06e7a5", "shasum": "" }, "require": { @@ -670,19 +619,19 @@ "ext-reflection": "*", "ext-spl": "*", "php": ">=5.3.3", - "phpspec/prophecy": "^1.3.1", - "phpunit/php-code-coverage": "~2.1", - "phpunit/php-file-iterator": "~1.4", + "phpspec/prophecy": "~1.3.1", + "phpunit/php-code-coverage": "~2.0", + "phpunit/php-file-iterator": "~1.3.2", "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": ">=1.0.6", + "phpunit/php-timer": "~1.0.2", "phpunit/phpunit-mock-objects": "~2.3", "sebastian/comparator": "~1.1", - "sebastian/diff": "~1.2", - "sebastian/environment": "~1.3", + "sebastian/diff": "~1.1", + "sebastian/environment": "~1.2", "sebastian/exporter": "~1.2", "sebastian/global-state": "~1.0", "sebastian/version": "~1.0", - "symfony/yaml": "~2.1|~3.0" + "symfony/yaml": "~2.0" }, "suggest": { "phpunit/php-invoker": "~1.1" @@ -693,7 +642,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.8.x-dev" + "dev-master": "4.5.x-dev" } }, "autoload": { @@ -719,30 +668,29 @@ "testing", "xunit" ], - "time": "2016-03-14 06:16:08" + "time": "2015-02-05 15:51:19" }, { "name": "phpunit/phpunit-mock-objects", - "version": "2.3.8", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" + "reference": "c63d2367247365f688544f0d500af90a11a44c65" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", - "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/c63d2367247365f688544f0d500af90a11a44c65", + "reference": "c63d2367247365f688544f0d500af90a11a44c65", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.0.2", + "doctrine/instantiator": "~1.0,>=1.0.1", "php": ">=5.3.3", - "phpunit/php-text-template": "~1.2", - "sebastian/exporter": "~1.2" + "phpunit/php-text-template": "~1.2" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "~4.3" }, "suggest": { "ext-soap": "*" @@ -775,7 +723,7 @@ "mock", "xunit" ], - "time": "2015-10-02 06:51:40" + "time": "2014-10-03 05:12:11" }, { "name": "pimple/pimple", @@ -882,16 +830,16 @@ }, { "name": "sebastian/comparator", - "version": "1.2.0", + "version": "1.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "937efb279bd37a375bcadf584dec0726f84dbf22" + "reference": "1dd8869519a225f7f2b9eb663e225298fade819e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22", - "reference": "937efb279bd37a375bcadf584dec0726f84dbf22", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1dd8869519a225f7f2b9eb663e225298fade819e", + "reference": "1dd8869519a225f7f2b9eb663e225298fade819e", "shasum": "" }, "require": { @@ -905,7 +853,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" + "dev-master": "1.1.x-dev" } }, "autoload": { @@ -942,32 +890,32 @@ "compare", "equality" ], - "time": "2015-07-26 15:48:44" + "time": "2015-01-29 16:28:08" }, { "name": "sebastian/diff", - "version": "1.4.1", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" + "reference": "5843509fed39dee4b356a306401e9dd1a931fec7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", - "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/5843509fed39dee4b356a306401e9dd1a931fec7", + "reference": "5843509fed39dee4b356a306401e9dd1a931fec7", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { - "phpunit/phpunit": "~4.8" + "phpunit/phpunit": "~4.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "1.2-dev" } }, "autoload": { @@ -990,36 +938,36 @@ } ], "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", + "homepage": "http://www.github.com/sebastianbergmann/diff", "keywords": [ "diff" ], - "time": "2015-12-08 07:14:41" + "time": "2014-08-15 10:29:00" }, { "name": "sebastian/environment", - "version": "1.3.5", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "dc7a29032cf72b54f36dac15a1ca5b3a1b6029bf" + "reference": "6e6c71d918088c251b181ba8b3088af4ac336dd7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/dc7a29032cf72b54f36dac15a1ca5b3a1b6029bf", - "reference": "dc7a29032cf72b54f36dac15a1ca5b3a1b6029bf", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6e6c71d918088c251b181ba8b3088af4ac336dd7", + "reference": "6e6c71d918088c251b181ba8b3088af4ac336dd7", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "~4.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" + "dev-master": "1.2.x-dev" } }, "autoload": { @@ -1044,20 +992,20 @@ "environment", "hhvm" ], - "time": "2016-02-26 18:40:46" + "time": "2014-10-25 08:00:45" }, { "name": "sebastian/exporter", - "version": "1.2.1", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "7ae5513327cb536431847bcc0c10edba2701064e" + "reference": "84839970d05254c73cde183a721c7af13aede943" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e", - "reference": "7ae5513327cb536431847bcc0c10edba2701064e", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/84839970d05254c73cde183a721c7af13aede943", + "reference": "84839970d05254c73cde183a721c7af13aede943", "shasum": "" }, "require": { @@ -1110,20 +1058,20 @@ "export", "exporter" ], - "time": "2015-06-21 07:55:53" + "time": "2015-01-27 07:23:06" }, { "name": "sebastian/global-state", - "version": "1.1.1", + "version": "1.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" + "reference": "c7428acdb62ece0a45e6306f1ae85e1c05b09c01" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/c7428acdb62ece0a45e6306f1ae85e1c05b09c01", + "reference": "c7428acdb62ece0a45e6306f1ae85e1c05b09c01", "shasum": "" }, "require": { @@ -1161,20 +1109,20 @@ "keywords": [ "global state" ], - "time": "2015-10-12 03:26:01" + "time": "2014-10-06 09:23:50" }, { "name": "sebastian/recursion-context", - "version": "1.0.2", + "version": "1.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "913401df809e99e4f47b27cdd781f4a258d58791" + "reference": "3989662bbb30a29d20d9faa04a846af79b276252" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/913401df809e99e4f47b27cdd781f4a258d58791", - "reference": "913401df809e99e4f47b27cdd781f4a258d58791", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/3989662bbb30a29d20d9faa04a846af79b276252", + "reference": "3989662bbb30a29d20d9faa04a846af79b276252", "shasum": "" }, "require": { @@ -1214,20 +1162,20 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2015-11-11 19:50:13" + "time": "2015-01-24 09:48:32" }, { "name": "sebastian/version", - "version": "1.0.6", + "version": "1.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" + "reference": "a77d9123f8e809db3fbdea15038c27a95da4058b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", - "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/a77d9123f8e809db3fbdea15038c27a95da4058b", + "reference": "a77d9123f8e809db3fbdea15038c27a95da4058b", "shasum": "" }, "type": "library", @@ -1249,31 +1197,27 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2015-06-21 13:59:46" + "time": "2014-12-15 14:25:24" }, { "name": "squizlabs/php_codesniffer", - "version": "2.6.0", + "version": "2.3.3", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "1bcdf03b068a530ac1962ce671dead356eeba43b" + "reference": "c1a26c729508f73560c1a4f767f60b8ab6b4a666" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/1bcdf03b068a530ac1962ce671dead356eeba43b", - "reference": "1bcdf03b068a530ac1962ce671dead356eeba43b", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/c1a26c729508f73560c1a4f767f60b8ab6b4a666", + "reference": "c1a26c729508f73560c1a4f767f60b8ab6b4a666", "shasum": "" }, "require": { - "ext-simplexml": "*", "ext-tokenizer": "*", "ext-xmlwriter": "*", "php": ">=5.1.2" }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, "bin": [ "scripts/phpcs", "scripts/phpcbf" @@ -1281,7 +1225,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -1327,30 +1271,30 @@ "phpcs", "standards" ], - "time": "2016-04-03 22:58:34" + "time": "2015-06-24 03:16:23" }, { "name": "symfony/console", - "version": "v2.8.4", + "version": "v2.6.4", + "target-dir": "Symfony/Component/Console", "source": { "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "9a5aef5fc0d4eff86853d44202b02be8d5a20154" + "url": "https://github.com/symfony/Console.git", + "reference": "e44154bfe3e41e8267d7a3794cd9da9a51cfac34" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/9a5aef5fc0d4eff86853d44202b02be8d5a20154", - "reference": "9a5aef5fc0d4eff86853d44202b02be8d5a20154", + "url": "https://api.github.com/repos/symfony/Console/zipball/e44154bfe3e41e8267d7a3794cd9da9a51cfac34", + "reference": "e44154bfe3e41e8267d7a3794cd9da9a51cfac34", "shasum": "" }, "require": { - "php": ">=5.3.9", - "symfony/polyfill-mbstring": "~1.0" + "php": ">=5.3.3" }, "require-dev": { "psr/log": "~1.0", - "symfony/event-dispatcher": "~2.1|~3.0.0", - "symfony/process": "~2.1|~3.0.0" + "symfony/event-dispatcher": "~2.1", + "symfony/process": "~2.1" }, "suggest": { "psr/log": "For using the console logger", @@ -1360,16 +1304,13 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.8-dev" + "dev-master": "2.6-dev" } }, "autoload": { - "psr-4": { + "psr-0": { "Symfony\\Component\\Console\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1377,149 +1318,46 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" }, { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" } ], "description": "Symfony Console Component", - "homepage": "https://symfony.com", - "time": "2016-03-17 09:19:04" + "homepage": "http://symfony.com", + "time": "2015-01-25 04:39:26" }, { "name": "symfony/filesystem", - "version": "v2.8.4", + "version": "v2.6.4", + "target-dir": "Symfony/Component/Filesystem", "source": { "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "f08ffdf229252cd2745558cb2112df43903bcae4" + "url": "https://github.com/symfony/Filesystem.git", + "reference": "a1f566d1f92e142fa1593f4555d6d89e3044a9b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/f08ffdf229252cd2745558cb2112df43903bcae4", - "reference": "f08ffdf229252cd2745558cb2112df43903bcae4", - "shasum": "" - }, - "require": { - "php": ">=5.3.9" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.8-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Filesystem\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Filesystem Component", - "homepage": "https://symfony.com", - "time": "2016-03-27 10:20:16" - }, - { - "name": "symfony/finder", - "version": "v2.8.4", - "source": { - "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "ca24cf2cd4e3826f571e0067e535758e73807aa1" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/ca24cf2cd4e3826f571e0067e535758e73807aa1", - "reference": "ca24cf2cd4e3826f571e0067e535758e73807aa1", - "shasum": "" - }, - "require": { - "php": ">=5.3.9" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.8-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\Finder\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Finder Component", - "homepage": "https://symfony.com", - "time": "2016-03-10 10:53:53" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.1.1", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "1289d16209491b584839022f29257ad859b8532d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/1289d16209491b584839022f29257ad859b8532d", - "reference": "1289d16209491b584839022f29257ad859b8532d", + "url": "https://api.github.com/repos/symfony/Filesystem/zipball/a1f566d1f92e142fa1593f4555d6d89e3044a9b7", + "reference": "a1f566d1f92e142fa1593f4555d6d89e3044a9b7", "shasum": "" }, "require": { "php": ">=5.3.3" }, - "suggest": { - "ext-mbstring": "For best performance" - }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "2.6-dev" } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - }, - "files": [ - "bootstrap.php" - ] + "psr-0": { + "Symfony\\Component\\Filesystem\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1527,55 +1365,93 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" }, { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" } ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" + "description": "Symfony Filesystem Component", + "homepage": "http://symfony.com", + "time": "2015-01-03 21:13:09" + }, + { + "name": "symfony/finder", + "version": "v2.6.4", + "target-dir": "Symfony/Component/Finder", + "source": { + "type": "git", + "url": "https://github.com/symfony/Finder.git", + "reference": "16513333bca64186c01609961a2bb1b95b5e1355" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/Finder/zipball/16513333bca64186c01609961a2bb1b95b5e1355", + "reference": "16513333bca64186c01609961a2bb1b95b5e1355", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\Component\\Finder\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" ], - "time": "2016-01-20 09:13:37" + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Symfony Finder Component", + "homepage": "http://symfony.com", + "time": "2015-01-03 08:01:59" }, { "name": "symfony/process", - "version": "v2.8.4", + "version": "v2.6.4", + "target-dir": "Symfony/Component/Process", "source": { "type": "git", - "url": "https://github.com/symfony/process.git", - "reference": "fb467471952ef5cf8497c029980e556b47545333" + "url": "https://github.com/symfony/Process.git", + "reference": "ecfc23e89d9967999fa5f60a1e9af7384396e9ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/fb467471952ef5cf8497c029980e556b47545333", - "reference": "fb467471952ef5cf8497c029980e556b47545333", + "url": "https://api.github.com/repos/symfony/Process/zipball/ecfc23e89d9967999fa5f60a1e9af7384396e9ae", + "reference": "ecfc23e89d9967999fa5f60a1e9af7384396e9ae", "shasum": "" }, "require": { - "php": ">=5.3.9" + "php": ">=5.3.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.8-dev" + "dev-master": "2.6-dev" } }, "autoload": { - "psr-4": { + "psr-0": { "Symfony\\Component\\Process\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1583,48 +1459,46 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" }, { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" } ], "description": "Symfony Process Component", - "homepage": "https://symfony.com", - "time": "2016-03-23 13:11:46" + "homepage": "http://symfony.com", + "time": "2015-01-25 04:39:26" }, { "name": "symfony/yaml", - "version": "v2.8.4", + "version": "v2.6.4", + "target-dir": "Symfony/Component/Yaml", "source": { "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "584e52cb8f788a887553ba82db6caacb1d6260bb" + "url": "https://github.com/symfony/Yaml.git", + "reference": "60ed7751671113cf1ee7d7778e691642c2e9acd8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/584e52cb8f788a887553ba82db6caacb1d6260bb", - "reference": "584e52cb8f788a887553ba82db6caacb1d6260bb", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/60ed7751671113cf1ee7d7778e691642c2e9acd8", + "reference": "60ed7751671113cf1ee7d7778e691642c2e9acd8", "shasum": "" }, "require": { - "php": ">=5.3.9" + "php": ">=5.3.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.8-dev" + "dev-master": "2.6-dev" } }, "autoload": { - "psr-4": { + "psr-0": { "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1632,43 +1506,39 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" }, { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" } ], "description": "Symfony Yaml Component", - "homepage": "https://symfony.com", - "time": "2016-03-04 07:54:35" + "homepage": "http://symfony.com", + "time": "2015-01-25 04:39:26" }, { "name": "twig/twig", - "version": "v1.24.0", + "version": "v1.18.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "3e5aa30ebfbafd5951fb1b01e338e1800ce7e0e8" + "reference": "4cf7464348e7f9893a93f7096a90b73722be99cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/3e5aa30ebfbafd5951fb1b01e338e1800ce7e0e8", - "reference": "3e5aa30ebfbafd5951fb1b01e338e1800ce7e0e8", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/4cf7464348e7f9893a93f7096a90b73722be99cf", + "reference": "4cf7464348e7f9893a93f7096a90b73722be99cf", "shasum": "" }, "require": { - "php": ">=5.2.7" - }, - "require-dev": { - "symfony/debug": "~2.7", - "symfony/phpunit-bridge": "~2.7" + "php": ">=5.2.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.24-dev" + "dev-master": "1.18-dev" } }, "autoload": { @@ -1703,7 +1573,7 @@ "keywords": [ "templating" ], - "time": "2016-01-25 21:22:18" + "time": "2015-01-25 17:32:08" } ], "aliases": [], diff --git a/phpseclib/Crypt/AES.php b/phpseclib/Crypt/AES.php index 8521eb5e..2696e0ab 100644 --- a/phpseclib/Crypt/AES.php +++ b/phpseclib/Crypt/AES.php @@ -11,13 +11,13 @@ * just a wrapper to Rijndael.php you may consider using Rijndael.php instead of * to save one include_once(). * - * If {@link self::setKeyLength() setKeyLength()} isn't called, it'll be calculated from - * {@link self::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's 136-bits - * it'll be null-padded to 192-bits and 192 bits will be the key length until {@link self::setKey() setKey()} + * If {@link \phpseclib\Crypt\AES::setKeyLength() setKeyLength()} isn't called, it'll be calculated from + * {@link \phpseclib\Crypt\AES::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's 136-bits + * it'll be null-padded to 192-bits and 192 bits will be the key length until {@link \phpseclib\Crypt\AES::setKey() setKey()} * is called, again, at which point, it'll be recalculated. * * Since \phpseclib\Crypt\AES extends \phpseclib\Crypt\Rijndael, some functions are available to be called that, in the context of AES, don't - * make a whole lot of sense. {@link self::setBlockLength() setBlockLength()}, for instance. Calling that function, + * make a whole lot of sense. {@link \phpseclib\Crypt\AES::setBlockLength() setBlockLength()}, for instance. Calling that function, * however possible, won't do anything (AES has a fixed block length whereas Rijndael has a variable one). * * Here's a short example of how to use this library: @@ -49,6 +49,8 @@ namespace phpseclib\Crypt; +use phpseclib\Crypt\Rijndael; + /** * Pure-PHP implementation of AES. * @@ -65,33 +67,31 @@ class AES extends Rijndael * * @see \phpseclib\Crypt\Rijndael::setBlockLength() * @access public - * @param int $length - * @throws \BadMethodCallException anytime it's called + * @param Integer $length */ function setBlockLength($length) { - throw new \BadMethodCallException('The block length cannot be set for AES.'); + return; } /** * Sets the key length * - * Valid key lengths are 128, 192, and 256. Set the link to bool(false) to disable a fixed 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. * * @see \phpseclib\Crypt\Rijndael:setKeyLength() * @access public - * @param int $length - * @throws \LengthException if the key length isn't supported + * @param Integer $length */ function setKeyLength($length) { switch ($length) { - case 128: - case 192: - case 256: + case 160: + $length = 192; break; - default: - throw new \LengthException('Key of size ' . $length . ' not supported by this algorithm. Only keys of sizes 128, 192 or 256 supported'); + case 224: + $length = 256; } parent::setKeyLength($length); } @@ -104,20 +104,25 @@ class AES extends Rijndael * @see \phpseclib\Crypt\Rijndael:setKey() * @see setKeyLength() * @access public - * @param string $key - * @throws \LengthException if the key length isn't supported + * @param String $key */ 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); + + if (!$this->explicit_key_length) { + $length = strlen($key); + switch (true) { + case $length <= 16: + $this->key_size = 16; + break; + case $length <= 24: + $this->key_size = 24; + break; + default: + $this->key_size = 32; + } + $this->_setEngine(); + } } } diff --git a/phpseclib/Crypt/Base.php b/phpseclib/Crypt/Base.php index 92a6f62b..715ab2a5 100644 --- a/phpseclib/Crypt/Base.php +++ b/phpseclib/Crypt/Base.php @@ -36,6 +36,8 @@ namespace phpseclib\Crypt; +use phpseclib\Crypt\Hash; + /** * Base Class for all \phpseclib\Crypt\* cipher classes * @@ -92,7 +94,7 @@ abstract class Base * Whirlpool available flag * * @see \phpseclib\Crypt\Base::_hashInlineCryptFunction() - * @var bool + * @var Boolean * @access private */ static $WHIRLPOOL_AVAILABLE; @@ -118,8 +120,8 @@ abstract class Base /** * The Encryption Mode * - * @see self::__construct() - * @var int + * @see \phpseclib\Crypt\Base::__construct() + * @var Integer * @access private */ var $mode; @@ -127,7 +129,7 @@ abstract class Base /** * The Block Length of the block cipher * - * @var int + * @var Integer * @access private */ var $block_size = 16; @@ -135,27 +137,27 @@ abstract class Base /** * The Key * - * @see self::setKey() - * @var string + * @see \phpseclib\Crypt\Base::setKey() + * @var String * @access private */ - var $key = false; + var $key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; /** * The Initialization Vector * - * @see self::setIV() - * @var string + * @see \phpseclib\Crypt\Base::setIV() + * @var String * @access private */ - var $iv = false; + var $iv; /** * A "sliding" Initialization Vector * - * @see self::enableContinuousBuffer() - * @see self::_clearBuffers() - * @var string + * @see \phpseclib\Crypt\Base::enableContinuousBuffer() + * @see \phpseclib\Crypt\Base::_clearBuffers() + * @var String * @access private */ var $encryptIV; @@ -163,9 +165,9 @@ abstract class Base /** * A "sliding" Initialization Vector * - * @see self::enableContinuousBuffer() - * @see self::_clearBuffers() - * @var string + * @see \phpseclib\Crypt\Base::enableContinuousBuffer() + * @see \phpseclib\Crypt\Base::_clearBuffers() + * @var String * @access private */ var $decryptIV; @@ -173,8 +175,8 @@ abstract class Base /** * Continuous Buffer status * - * @see self::enableContinuousBuffer() - * @var bool + * @see \phpseclib\Crypt\Base::enableContinuousBuffer() + * @var Boolean * @access private */ var $continuousBuffer = false; @@ -182,9 +184,9 @@ abstract class Base /** * Encryption buffer for CTR, OFB and CFB modes * - * @see self::encrypt() - * @see self::_clearBuffers() - * @var array + * @see \phpseclib\Crypt\Base::encrypt() + * @see \phpseclib\Crypt\Base::_clearBuffers() + * @var Array * @access private */ var $enbuffer; @@ -192,9 +194,9 @@ abstract class Base /** * Decryption buffer for CTR, OFB and CFB modes * - * @see self::decrypt() - * @see self::_clearBuffers() - * @var array + * @see \phpseclib\Crypt\Base::decrypt() + * @see \phpseclib\Crypt\Base::_clearBuffers() + * @var Array * @access private */ var $debuffer; @@ -205,8 +207,8 @@ abstract class Base * The mcrypt resource can be recreated every time something needs to be created or it can be created just once. * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode. * - * @see self::encrypt() - * @var resource + * @see \phpseclib\Crypt\Base::encrypt() + * @var Resource * @access private */ var $enmcrypt; @@ -217,8 +219,8 @@ abstract class Base * The mcrypt resource can be recreated every time something needs to be created or it can be created just once. * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode. * - * @see self::decrypt() - * @var resource + * @see \phpseclib\Crypt\Base::decrypt() + * @var Resource * @access private */ var $demcrypt; @@ -228,7 +230,7 @@ abstract class Base * * @see \phpseclib\Crypt\Twofish::setKey() * @see \phpseclib\Crypt\Twofish::setIV() - * @var bool + * @var Boolean * @access private */ var $enchanged = true; @@ -238,7 +240,7 @@ abstract class Base * * @see \phpseclib\Crypt\Twofish::setKey() * @see \phpseclib\Crypt\Twofish::setIV() - * @var bool + * @var Boolean * @access private */ var $dechanged = true; @@ -254,10 +256,10 @@ abstract class Base * use a separate ECB-mode mcrypt resource. * * @link http://phpseclib.sourceforge.net/cfb-demo.phps - * @see self::encrypt() - * @see self::decrypt() - * @see self::_setupMcrypt() - * @var resource + * @see \phpseclib\Crypt\Base::encrypt() + * @see \phpseclib\Crypt\Base::decrypt() + * @see \phpseclib\Crypt\Base::_setupMcrypt() + * @var Resource * @access private */ var $ecb; @@ -278,8 +280,8 @@ abstract class Base * which, typically, depends on the complexity * on its internaly Key-expanding algorithm. * - * @see self::encrypt() - * @var int + * @see \phpseclib\Crypt\Base::encrypt() + * @var Integer * @access private */ var $cfb_init_len = 600; @@ -287,10 +289,10 @@ abstract class Base /** * Does internal cipher state need to be (re)initialized? * - * @see self::setKey() - * @see self::setIV() - * @see self::disableContinuousBuffer() - * @var bool + * @see setKey() + * @see setIV() + * @see disableContinuousBuffer() + * @var Boolean * @access private */ var $changed = true; @@ -298,8 +300,8 @@ abstract class Base /** * Padding status * - * @see self::enablePadding() - * @var bool + * @see \phpseclib\Crypt\Base::enablePadding() + * @var Boolean * @access private */ var $padding = true; @@ -307,8 +309,8 @@ abstract class Base /** * Is the mode one that is paddable? * - * @see self::__construct() - * @var bool + * @see \phpseclib\Crypt\Base::__construct() + * @var Boolean * @access private */ var $paddable = false; @@ -322,10 +324,10 @@ abstract class Base * - self::ENGINE_MCRYPT (fast, php-extension: mcrypt, extension_loaded('mcrypt') required) * - self::ENGINE_INTERNAL (slower, pure php-engine, no php-extension required) * - * @see self::_setEngine() - * @see self::encrypt() - * @see self::decrypt() - * @var int + * @see \phpseclib\Crypt\Base::_setEngine() + * @see \phpseclib\Crypt\Base::encrypt() + * @see \phpseclib\Crypt\Base::decrypt() + * @var Integer * @access private */ var $engine; @@ -333,9 +335,9 @@ abstract class Base /** * Holds the preferred crypt engine * - * @see self::_setEngine() - * @see self::setPreferredEngine() - * @var int + * @see \phpseclib\Crypt\Base::_setEngine() + * @see \phpseclib\Crypt\Base::setPreferredEngine() + * @var Integer * @access private */ var $preferredEngine; @@ -347,8 +349,8 @@ abstract class Base * * @link http://www.php.net/mcrypt_module_open * @link http://www.php.net/mcrypt_list_algorithms - * @see self::_setupMcrypt() - * @var string + * @see \phpseclib\Crypt\Base::_setupMcrypt() + * @var String * @access private */ var $cipher_name_mcrypt; @@ -356,10 +358,10 @@ abstract class Base /** * The openssl specific name of the cipher * - * Only used if $engine == self::ENGINE_OPENSSL + * Only used if $engine == CRYPT_ENGINE_OPENSSL * * @link http://www.php.net/openssl-get-cipher-methods - * @var string + * @var String * @access private */ var $cipher_name_openssl; @@ -371,16 +373,25 @@ abstract class Base * it can still be emulated with ECB mode. * * @link http://www.php.net/openssl-get-cipher-methods - * @var string + * @var String * @access private */ var $cipher_name_openssl_ecb; + /** + * The default password key_size used by setPassword() + * + * @see \phpseclib\Crypt\Base::setPassword() + * @var Integer + * @access private + */ + var $password_key_size = 32; + /** * The default salt used by setPassword() * - * @see self::setPassword() - * @var string + * @see \phpseclib\Crypt\Base::setPassword() + * @var String * @access private */ var $password_default_salt = 'phpseclib/salt'; @@ -391,10 +402,10 @@ abstract class Base * Used by encrypt() / decrypt() * only if $engine == self::ENGINE_INTERNAL * - * @see self::encrypt() - * @see self::decrypt() - * @see self::_setupInlineCrypt() - * @see self::$use_inline_crypt + * @see \phpseclib\Crypt\Base::encrypt() + * @see \phpseclib\Crypt\Base::decrypt() + * @see \phpseclib\Crypt\Base::_setupInlineCrypt() + * @see \phpseclib\Crypt\Base::$use_inline_crypt * @var Callback * @access private */ @@ -403,9 +414,9 @@ abstract class Base /** * Holds whether performance-optimized $inline_crypt() can/should be used. * - * @see self::encrypt() - * @see self::decrypt() - * @see self::inline_crypt + * @see \phpseclib\Crypt\Base::encrypt() + * @see \phpseclib\Crypt\Base::decrypt() + * @see \phpseclib\Crypt\Base::inline_crypt * @var mixed * @access private */ @@ -414,8 +425,8 @@ abstract class Base /** * If OpenSSL can be used in ECB but not in CTR we can emulate CTR * - * @see self::_openssl_ctr_process() - * @var bool + * @see \phpseclib\Crypt\Base::_openssl_ctr_process() + * @var Boolean * @access private */ var $openssl_emulate_ctr = false; @@ -423,33 +434,17 @@ abstract class Base /** * Determines what options are passed to openssl_encrypt/decrypt * - * @see self::isValidEngine() + * @see \phpseclib\Crypt\Base::isValidEngine() * @var mixed * @access private */ var $openssl_options; - /** - * Don't truncate / null pad key - * - * @see self::_clearBuffers() - * @var bool - * @access private - */ - var $skip_key_adjustment = false; - - /** - * 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; - /** * Default Constructor. * + * Determines whether or not the mcrypt extension should be used. + * * $mode could be: * * - self::MODE_ECB @@ -462,29 +457,34 @@ abstract class Base * * - self::MODE_OFB * - * @param int $mode + * (or the alias constants of the chosen cipher, for example for AES: CRYPT_AES_MODE_ECB or CRYPT_AES_MODE_CBC ...) + * + * If not explicitly set, self::MODE_CBC will be used. + * + * @param optional Integer $mode * @access public - * @throws \InvalidArgumentException if an invalid / unsupported mode is provided */ - function __construct($mode) + function __construct($mode = self::MODE_CBC) { // $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_OFB: case self::MODE_STREAM: - $this->paddable = false; + $this->mode = $mode; break; + case self::MODE_CBC: default: - throw new \InvalidArgumentException('No valid mode has been specified'); + $this->paddable = true; + $this->mode = self::MODE_CBC; } - $this->mode = $mode; + $this->_setEngine(); // Determining whether inline crypting can be used by the cipher if ($this->use_inline_crypt !== false && function_exists('create_function')) { @@ -493,85 +493,25 @@ abstract class Base } /** - * Sets the initialization vector. + * Sets the initialization vector. (optional) * - * setIV() is not required when self::MODE_ECB (or ie for AES: \phpseclib\Crypt\AES::MODE_ECB) is being used. + * 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. * * @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 + * @param String $iv * @internal Can be overwritten by a sub class, but does not have to be */ function setIV($iv) { if ($this->mode == self::MODE_ECB) { - 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'); + return; } $this->iv = $iv; $this->changed = true; } - /** - * Returns whether or not the algorithm uses an IV - * - * @access public - * @return bool - */ - function usesIV() - { - return true; - } - - /** - * Returns the current key length in bits - * - * @access public - * @return int - */ - function getKeyLength() - { - return $this->key_length << 3; - } - - /** - * Returns the current block length in bits - * - * @access public - * @return int - */ - function getBlockLength() - { - return $this->block_size << 3; - } - - /** - * Sets the key 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. * @@ -583,17 +523,12 @@ abstract class Base * If the key is not explicitly set, it'll be assumed to be all null bytes. * * @access public - * @param string $key + * @param String $key * @internal Could, but not must, extend by the child Crypt_* class */ function setKey($key) { - if ($this->explicit_key_length !== 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(); } @@ -608,10 +543,9 @@ abstract class Base * Where $hash (default = sha1) currently supports the following hashes: see: Crypt/Hash.php * * @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 + * @param String $password + * @param optional String $method + * @return Boolean * @access public * @internal Could, but not must, extend by the child Crypt_* class */ @@ -637,8 +571,7 @@ abstract class Base if (isset($func_args[5])) { $dkLen = $func_args[5]; } else { - $key_length = $this->explicit_key_length !== false ? $this->explicit_key_length : $this->key_length; - $dkLen = $method == 'pbkdf1' ? 2 * $key_length : $key_length; + $dkLen = $method == 'pbkdf1' ? 2 * $this->password_key_size : $this->password_key_size; } switch (true) { @@ -646,7 +579,8 @@ abstract class Base $hashObj = new Hash(); $hashObj->setHash($hash); if ($dkLen > $hashObj->getLength()) { - throw new \LengthException('Derived key length cannot be longer than the hash length'); + user_error('Derived key too long'); + return false; } $t = $password . $salt; for ($i = 0; $i < $count; ++$i) { @@ -700,10 +634,10 @@ abstract class Base * strlen($plaintext) will still need to be a multiple of the block size, however, arbitrary values can be added to make it that * length. * - * @see self::decrypt() + * @see \phpseclib\Crypt\Base::decrypt() * @access public - * @param string $plaintext - * @return string $ciphertext + * @param String $plaintext + * @return String $ciphertext * @internal Could, but not must, extend by the child Crypt_* class */ function encrypt($plaintext) @@ -725,13 +659,10 @@ abstract class Base return !defined('OPENSSL_RAW_DATA') ? substr($result, 0, -$this->block_size) : $result; case self::MODE_CBC: $result = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->encryptIV); - if (!defined('OPENSSL_RAW_DATA')) { - $result = substr($result, 0, -$this->block_size); - } if ($this->continuousBuffer) { $this->encryptIV = substr($result, -$this->block_size); } - return $result; + return !defined('OPENSSL_RAW_DATA') ? substr($result, 0, -$this->block_size) : $result; case self::MODE_CTR: return $this->_openssl_ctr_process($plaintext, $this->encryptIV, $this->enbuffer); case self::MODE_CFB: @@ -793,7 +724,7 @@ abstract class Base $this->changed = false; } if ($this->enchanged) { - mcrypt_generic_init($this->enmcrypt, $this->key, $this->_getIV($this->encryptIV)); + mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV); $this->enchanged = false; } @@ -856,7 +787,7 @@ abstract class Base $ciphertext = mcrypt_generic($this->enmcrypt, $plaintext); if (!$this->continuousBuffer) { - mcrypt_generic_init($this->enmcrypt, $this->key, $this->_getIV($this->encryptIV)); + mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV); } return $ciphertext; @@ -983,7 +914,7 @@ abstract class Base if ($this->continuousBuffer) { $this->encryptIV = $xor; if ($start = strlen($plaintext) % $block_size) { - $buffer['xor'] = substr($key, $start) . $buffer['xor']; + $buffer['xor'] = substr($key, $start) . $buffer['xor']; } } break; @@ -1001,17 +932,18 @@ abstract class Base * If strlen($ciphertext) is not a multiple of the block size, null bytes will be added to the end of the string until * it is. * - * @see self::encrypt() + * @see \phpseclib\Crypt\Base::encrypt() * @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 + * @param String $ciphertext + * @return String $plaintext * @internal Could, but not must, extend by the child Crypt_* class */ function decrypt($ciphertext) { - 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->paddable) { + // we pad with chr(0) since that's what mcrypt_generic does. to quote from {@link http://www.php.net/function.mcrypt-generic}: + // "The data is padded with "\0" to make sure the length of the data is n * blocksize." + $ciphertext = str_pad($ciphertext, strlen($ciphertext) + ($this->block_size - strlen($ciphertext) % $this->block_size) % $this->block_size, chr(0)); } if ($this->engine === self::ENGINE_OPENSSL) { @@ -1025,7 +957,7 @@ abstract class Base break; case self::MODE_ECB: if (!defined('OPENSSL_RAW_DATA')) { - $ciphertext.= openssl_encrypt('', $this->cipher_name_openssl_ecb, $this->key, true); + $ciphetext.= openssl_encrypt('', $this->cipher_name_openssl_ecb, $this->key, true); } $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options); break; @@ -1033,13 +965,10 @@ abstract class Base if (!defined('OPENSSL_RAW_DATA')) { $padding = str_repeat(chr($this->block_size), $this->block_size) ^ substr($ciphertext, -$this->block_size); $ciphertext.= substr(openssl_encrypt($padding, $this->cipher_name_openssl_ecb, $this->key, true), 0, $this->block_size); - $offset = 2 * $this->block_size; - } else { - $offset = $this->block_size; } $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->decryptIV); if ($this->continuousBuffer) { - $this->decryptIV = substr($ciphertext, -$offset, $this->block_size); + $this->decryptIV = substr($ciphertext, -$this->block_size); } break; case self::MODE_CTR: @@ -1104,7 +1033,7 @@ abstract class Base $this->changed = false; } if ($this->dechanged) { - mcrypt_generic_init($this->demcrypt, $this->key, $this->_getIV($this->decryptIV)); + mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV); $this->dechanged = false; } @@ -1149,7 +1078,7 @@ abstract class Base $plaintext = mdecrypt_generic($this->demcrypt, $ciphertext); if (!$this->continuousBuffer) { - mcrypt_generic_init($this->demcrypt, $this->key, $this->_getIV($this->decryptIV)); + mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV); } return $this->paddable ? $this->_unpad($plaintext) : $plaintext; @@ -1275,7 +1204,7 @@ abstract class Base if ($this->continuousBuffer) { $this->decryptIV = $xor; if ($start = strlen($ciphertext) % $block_size) { - $buffer['xor'] = substr($key, $start) . $buffer['xor']; + $buffer['xor'] = substr($key, $start) . $buffer['xor']; } } break; @@ -1286,36 +1215,20 @@ 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 + * for CTR is the same for both encrypting and decrypting this function is re-used by both Crypt_Base::encrypt() + * and Crypt_Base::decrypt(). Also, OpenSSL doesn't implement CTR for all of it's symmetric ciphers so this * function will emulate CTR with ECB when necesary. * - * @see self::encrypt() - * @see self::decrypt() - * @param string $plaintext - * @param string $encryptIV - * @param array $buffer - * @return string + * @see Crypt_Base::encrypt() + * @see Crypt_Base::decrypt() + * @param String $plaintext + * @param String $encryptIV + * @param Array $buffer + * @return String * @access private */ function _openssl_ctr_process($plaintext, &$encryptIV, &$buffer) @@ -1401,15 +1314,15 @@ abstract class Base * OpenSSL OFB Processor * * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream - * for OFB is the same for both encrypting and decrypting this function is re-used by both Base::encrypt() - * and Base::decrypt(). + * for OFB is the same for both encrypting and decrypting this function is re-used by both Crypt_Base::encrypt() + * and Crypt_Base::decrypt(). * - * @see self::encrypt() - * @see self::decrypt() - * @param string $plaintext - * @param string $encryptIV - * @param array $buffer - * @return string + * @see Crypt_Base::encrypt() + * @see Crypt_Base::decrypt() + * @param String $plaintext + * @param String $encryptIV + * @param Array $buffer + * @return String * @access private */ function _openssl_ofb_process($plaintext, &$encryptIV, &$buffer) @@ -1455,7 +1368,7 @@ abstract class Base * * May need to be overwritten by classes extending this one in some cases * - * @return int + * @return Integer * @access private */ function _openssl_translate_mode() @@ -1486,7 +1399,7 @@ abstract class Base * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is * transmitted separately) * - * @see self::disablePadding() + * @see \phpseclib\Crypt\Base::disablePadding() * @access public */ function enablePadding() @@ -1497,7 +1410,7 @@ abstract class Base /** * Do not pad packets. * - * @see self::enablePadding() + * @see \phpseclib\Crypt\Base::enablePadding() * @access public */ function disablePadding() @@ -1539,7 +1452,7 @@ abstract class Base * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them), * however, they are also less intuitive and more likely to cause you problems. * - * @see self::disableContinuousBuffer() + * @see \phpseclib\Crypt\Base::disableContinuousBuffer() * @access public * @internal Could, but not must, extend by the child Crypt_* class */ @@ -1559,7 +1472,7 @@ abstract class Base * * The default behavior. * - * @see self::enableContinuousBuffer() + * @see \phpseclib\Crypt\Base::enableContinuousBuffer() * @access public * @internal Could, but not must, extend by the child Crypt_* class */ @@ -1581,10 +1494,10 @@ abstract class Base /** * Test for engine validity * - * @see self::__construct() - * @param int $engine + * @see \phpseclib\Crypt\Base::Crypt_Base() + * @param Integer $engine * @access public - * @return bool + * @return Boolean */ function isValidEngine($engine) { @@ -1648,8 +1561,8 @@ abstract class Base * * If the preferred crypt engine is not available the fastest available one will be used * - * @see self::__construct() - * @param int $engine + * @see \phpseclib\Crypt\Base::Crypt_Base() + * @param Integer $engine * @access public */ function setPreferredEngine($engine) @@ -1670,7 +1583,7 @@ abstract class Base /** * Returns the engine currently being utilized * - * @see self::_setEngine() + * @see \phpseclib\Crypt\Base::_setEngine() * @access public */ function getEngine() @@ -1681,7 +1594,7 @@ abstract class Base /** * Sets the engine as appropriate * - * @see self::__construct() + * @see \phpseclib\Crypt\Base::Crypt_Base() * @access private */ function _setEngine() @@ -1726,8 +1639,8 @@ abstract class Base * Note: Must be extended by the child \phpseclib\Crypt\* class * * @access private - * @param string $in - * @return string + * @param String $in + * @return String */ abstract function _encryptBlock($in); @@ -1737,8 +1650,8 @@ abstract class Base * Note: Must be extended by the child \phpseclib\Crypt\* class * * @access private - * @param string $in - * @return string + * @param String $in + * @return String */ abstract function _decryptBlock($in); @@ -1749,7 +1662,7 @@ abstract class Base * * Note: Must extend by the child \phpseclib\Crypt\* class * - * @see self::_setup() + * @see \phpseclib\Crypt\Base::_setup() * @access private */ abstract function _setupKey(); @@ -1771,9 +1684,9 @@ abstract class Base * * - First run of encrypt() / decrypt() with no init-settings * - * @see self::setKey() - * @see self::setIV() - * @see self::disableContinuousBuffer() + * @see setKey() + * @see setIV() + * @see disableContinuousBuffer() * @access private * @internal _setup() is always called before en/decryption. * @internal Could, but not must, extend by the child Crypt_* class @@ -1805,9 +1718,9 @@ abstract class Base * * - First run of encrypt() / decrypt() * - * @see self::setKey() - * @see self::setIV() - * @see self::disableContinuousBuffer() + * @see setKey() + * @see setIV() + * @see disableContinuousBuffer() * @access private * @internal Could, but not must, extend by the child Crypt_* class */ @@ -1835,6 +1748,7 @@ abstract class Base if ($this->mode == self::MODE_CFB) { $this->ecb = mcrypt_module_open($this->cipher_name_mcrypt, '', MCRYPT_MODE_ECB, ''); } + } // else should mcrypt_generic_deinit be called? if ($this->mode == self::MODE_CFB) { @@ -1852,11 +1766,10 @@ abstract class Base * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless * and padding will, hence forth, be enabled. * - * @see self::_unpad() - * @param string $text - * @throws \LengthException if padding is disabled and the plaintext's length is not a multiple of the block size + * @see \phpseclib\Crypt\Base::_unpad() + * @param String $text * @access private - * @return string + * @return String */ function _pad($text) { @@ -1866,7 +1779,8 @@ abstract class Base if ($length % $this->block_size == 0) { return $text; } else { - throw new \LengthException("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size}). Try enabling padding."); + user_error("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size})"); + $this->padding = true; } } @@ -1881,11 +1795,10 @@ abstract class Base * If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong * and false will be returned. * - * @see self::_pad() - * @param string $text - * @throws \LengthException if the ciphertext's length is not a multiple of the block size + * @see \phpseclib\Crypt\Base::_pad() + * @param String $text * @access private - * @return string + * @return String */ function _unpad($text) { @@ -1896,7 +1809,7 @@ abstract class Base $length = ord($text[strlen($text) - 1]); if (!$length || $length > $this->block_size) { - throw new \LengthException("The ciphertext has an invalid padding length ($length) compared to the block size ({$this->block_size})"); + return false; } return substr($text, 0, -$length); @@ -1909,19 +1822,16 @@ abstract class Base * after disableContinuousBuffer() or on cipher $engine (re)init * ie after setKey() or setIV() * - * @access private + * @access public * @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); - 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; + // 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"); } /** @@ -1929,10 +1839,10 @@ abstract class Base * * Inspired by array_shift * - * @param string $string - * @param int $index + * @param String $string + * @param optional Integer $index * @access private - * @return string + * @return String */ function _string_shift(&$string, $index = 1) { @@ -1946,10 +1856,10 @@ abstract class Base * * Inspired by array_pop * - * @param string $string - * @param int $index + * @param String $string + * @param optional Integer $index * @access private - * @return string + * @return String */ function _string_pop(&$string, $index = 1) { @@ -1961,9 +1871,9 @@ abstract class Base /** * Increment the current string * - * @see self::decrypt() - * @see self::encrypt() - * @param string $var + * @see \phpseclib\Crypt\Base::decrypt() + * @see \phpseclib\Crypt\Base::encrypt() + * @param String $var * @access private */ function _increment_str(&$var) @@ -2048,10 +1958,10 @@ abstract class Base * - The callback function should not use the 'return' statement, but en/decrypt'ing the content of $in only * * - * @see self::_setup() - * @see self::_createInlineCryptFunction() - * @see self::encrypt() - * @see self::decrypt() + * @see \phpseclib\Crypt\Base::_setup() + * @see \phpseclib\Crypt\Base::_createInlineCryptFunction() + * @see \phpseclib\Crypt\Base::encrypt() + * @see \phpseclib\Crypt\Base::decrypt() * @access private * @internal If a Crypt_* class providing inline crypting it must extend _setupInlineCrypt() */ @@ -2170,12 +2080,12 @@ abstract class Base * ); * * - * @see self::_setupInlineCrypt() - * @see self::encrypt() - * @see self::decrypt() - * @param array $cipher_code + * @see \phpseclib\Crypt\Base::_setupInlineCrypt() + * @see \phpseclib\Crypt\Base::encrypt() + * @see \phpseclib\Crypt\Base::decrypt() + * @param Array $cipher_code * @access private - * @return string (the name of the created callback function) + * @return String (the name of the created callback function) */ function _createInlineCryptFunction($cipher_code) { @@ -2542,7 +2452,7 @@ abstract class Base * for which $mode the lambda function was created. * * @access private - * @return array &$functions + * @return Array &$functions */ function &_getLambdaFunctions() { @@ -2553,10 +2463,10 @@ abstract class Base /** * Generates a digest from $bytes * - * @see self::_setupInlineCrypt() + * @see _setupInlineCrypt() * @access private * @param $bytes - * @return string + * @return String */ function _hashInlineCryptFunction($bytes) { diff --git a/phpseclib/Crypt/Blowfish.php b/phpseclib/Crypt/Blowfish.php index 3500df59..9844bafa 100644 --- a/phpseclib/Crypt/Blowfish.php +++ b/phpseclib/Crypt/Blowfish.php @@ -37,6 +37,8 @@ namespace phpseclib\Crypt; +use phpseclib\Crypt\Base; + /** * Pure-PHP implementation of Blowfish. * @@ -51,16 +53,26 @@ class Blowfish extends Base * Block Length of the cipher * * @see \phpseclib\Crypt\Base::block_size - * @var int + * @var Integer * @access private */ var $block_size = 8; + /** + * The default password key_size used by setPassword() + * + * @see \phpseclib\Crypt\Base::password_key_size + * @see \phpseclib\Crypt\Base::setPassword() + * @var Integer + * @access private + */ + var $password_key_size = 56; + /** * The mcrypt specific name of the cipher * * @see \phpseclib\Crypt\Base::cipher_name_mcrypt - * @var string + * @var String * @access private */ var $cipher_name_mcrypt = 'blowfish'; @@ -69,7 +81,7 @@ class Blowfish extends Base * Optimizing value while CFB-encrypting * * @see \phpseclib\Crypt\Base::cfb_init_len - * @var int + * @var Integer * @access private */ var $cfb_init_len = 500; @@ -82,7 +94,7 @@ class Blowfish extends Base * @access private * @var array */ - var $sbox0 = array( + var $sbox0 = array ( 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, @@ -265,73 +277,53 @@ class Blowfish extends Base /** * Holds the last used key * - * @var array + * @var Array * @access private */ var $kl; /** - * The Key Length (in bytes) + * Sets the key. * - * @see \phpseclib\Crypt\Base::setKeyLength() - * @var int - * @access private - * @internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16. Exists in conjunction with $Nk - * because the encryption / decryption / key schedule creation requires this number and not $key_length. We could - * derive this from $key_length or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu - * of that, we'll just precompute it once. - */ - var $key_length = 16; - - /** - * Default Constructor. + * Keys can be of any length. Blowfish, itself, requires the use of a key between 32 and max. 448-bits long. + * If the key is less than 32-bits we NOT fill the key to 32bit but let the key as it is to be compatible + * with mcrypt because mcrypt act this way with blowfish key's < 32 bits. * - * @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. + * If the key is more than 448-bits, we trim the excess bits. * - * Key lengths can be between 32 and 448 bits. + * If the key is not explicitly set, or empty, it'll be assumed a 128 bits key to be all null bytes. * * @access public - * @param int $length + * @see \phpseclib\Crypt\Base::setKey() + * @param String $key */ - function setKeyLength($length) + function setKey($key) { - 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'); + $keylength = strlen($key); + + if (!$keylength) { + $key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; + } elseif ($keylength > 56) { + $key = substr($key, 0, 56); } - $this->key_length = $length >> 3; - - parent::setKeyLength($length); + parent::setKey($key); } /** * Test for engine validity * - * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine() + * This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine() * * @see \phpseclib\Crypt\Base::isValidEngine() - * @param int $engine + * @param Integer $engine * @access public - * @return bool + * @return Boolean */ function isValidEngine($engine) { if ($engine == self::ENGINE_OPENSSL) { - if ($this->key_length != 16) { + if (strlen($this->key) != 16) { return false; } $this->cipher_name_openssl_ecb = 'bf-ecb'; @@ -401,8 +393,8 @@ class Blowfish extends Base * Encrypts a block * * @access private - * @param string $in - * @return string + * @param String $in + * @return String */ function _encryptBlock($in) { @@ -437,8 +429,8 @@ class Blowfish extends Base * Decrypts a block * * @access private - * @param string $in - * @return string + * @param String $in + * @return String */ function _decryptBlock($in) { @@ -479,9 +471,9 @@ class Blowfish extends Base $lambda_functions =& self::_getLambdaFunctions(); // We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function. - // (Currently, for Blowfish, one generated $lambda_function cost on php5.5@32bit ~100kb unfreeable mem and ~180kb on php5.5@64bit) + // (Currently, for Crypt_Blowfish, one generated $lambda_function cost on php5.5@32bit ~100kb unfreeable mem and ~180kb on php5.5@64bit) // After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one. - $gen_hi_opt_code = (bool)(count($lambda_functions) < 10); + $gen_hi_opt_code = (bool)( count($lambda_functions) < 10 ); // Generation of a unique hash for our generated code $code_hash = "Crypt_Blowfish, {$this->mode}"; diff --git a/phpseclib/Crypt/DES.php b/phpseclib/Crypt/DES.php index 14273d28..d748f1a5 100644 --- a/phpseclib/Crypt/DES.php +++ b/phpseclib/Crypt/DES.php @@ -42,6 +42,8 @@ namespace phpseclib\Crypt; +use phpseclib\Crypt\Base; + /** * Pure-PHP implementation of DES. * @@ -62,7 +64,7 @@ class DES extends Base const ENCRYPT = 0; /** * Contains $keys[self::DECRYPT] - */ + */ const DECRYPT = 1; /**#@-*/ @@ -70,25 +72,36 @@ class DES extends Base * Block Length of the cipher * * @see \phpseclib\Crypt\Base::block_size - * @var int + * @var Integer * @access private */ var $block_size = 8; /** - * Key Length (in bytes) + * The Key * - * @see \phpseclib\Crypt\Base::setKeyLength() - * @var int + * @see \phpseclib\Crypt\Base::key + * @see setKey() + * @var String * @access private */ - var $key_length = 8; + var $key = "\0\0\0\0\0\0\0\0"; + + /** + * The default password key_size used by setPassword() + * + * @see \phpseclib\Crypt\Base::password_key_size + * @see \phpseclib\Crypt\Base::setPassword() + * @var Integer + * @access private + */ + var $password_key_size = 8; /** * The mcrypt specific name of the cipher * * @see \phpseclib\Crypt\Base::cipher_name_mcrypt - * @var string + * @var String * @access private */ var $cipher_name_mcrypt = 'des'; @@ -97,7 +110,7 @@ class DES extends Base * The OpenSSL names of the cipher / modes * * @see \phpseclib\Crypt\Base::openssl_mode_names - * @var array + * @var Array * @access private */ var $openssl_mode_names = array( @@ -112,7 +125,7 @@ class DES extends Base * Optimizing value while CFB-encrypting * * @see \phpseclib\Crypt\Base::cfb_init_len - * @var int + * @var Integer * @access private */ var $cfb_init_len = 500; @@ -122,9 +135,9 @@ class DES extends Base * * Used only if $engine == self::ENGINE_INTERNAL * - * @see self::_setupKey() - * @see self::_processBlock() - * @var int + * @see \phpseclib\Crypt\DES::_setupKey() + * @see \phpseclib\Crypt\DES::_processBlock() + * @var Integer * @access private */ var $des_rounds = 1; @@ -132,17 +145,17 @@ class DES extends Base /** * max possible size of $key * - * @see self::setKey() - * @var string + * @see \phpseclib\Crypt\DES::setKey() + * @var String * @access private */ - var $key_length_max = 8; + var $key_size_max = 8; /** * The Key Schedule * - * @see self::_setupKey() - * @var array + * @see \phpseclib\Crypt\DES::_setupKey() + * @var Array * @access private */ var $keys; @@ -154,9 +167,9 @@ class DES extends Base * with each byte containing all bits in the same state as the * corresponding bit in the index value. * - * @see self::_processBlock() - * @see self::_setupKey() - * @var array + * @see \phpseclib\Crypt\DES::_processBlock() + * @see \phpseclib\Crypt\DES::_setupKey() + * @var Array * @access private */ var $shuffle = array( @@ -295,7 +308,7 @@ class DES extends Base * * Indexing this table with each source byte performs the initial bit permutation. * - * @var array + * @var Array * @access private */ var $ipmap = array( @@ -337,7 +350,7 @@ class DES extends Base * Inverse IP mapping helper table. * Indexing this table with a byte value reverses the bit order. * - * @var array + * @var Array * @access private */ var $invipmap = array( @@ -381,7 +394,7 @@ class DES extends Base * Each box ($sbox1-$sbox8) has been vectorized, then each value pre-permuted using the * P table: concatenation can then be replaced by exclusive ORs. * - * @var array + * @var Array * @access private */ var $sbox1 = array( @@ -406,7 +419,7 @@ class DES extends Base /** * Pre-permuted S-box2 * - * @var array + * @var Array * @access private */ var $sbox2 = array( @@ -431,7 +444,7 @@ class DES extends Base /** * Pre-permuted S-box3 * - * @var array + * @var Array * @access private */ var $sbox3 = array( @@ -456,7 +469,7 @@ class DES extends Base /** * Pre-permuted S-box4 * - * @var array + * @var Array * @access private */ var $sbox4 = array( @@ -481,7 +494,7 @@ class DES extends Base /** * Pre-permuted S-box5 * - * @var array + * @var Array * @access private */ var $sbox5 = array( @@ -506,7 +519,7 @@ class DES extends Base /** * Pre-permuted S-box6 * - * @var array + * @var Array * @access private */ var $sbox6 = array( @@ -531,7 +544,7 @@ class DES extends Base /** * Pre-permuted S-box7 * - * @var array + * @var Array * @access private */ var $sbox7 = array( @@ -556,7 +569,7 @@ class DES extends Base /** * Pre-permuted S-box8 * - * @var array + * @var Array * @access private */ var $sbox8 = array( @@ -578,35 +591,19 @@ 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 * - * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine() + * This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine() * * @see \phpseclib\Crypt\Base::isValidEngine() - * @param int $engine + * @param Integer $engine * @access public - * @return bool + * @return Boolean */ function isValidEngine($engine) { - if ($this->key_length_max == 8) { + if ($this->key_size_max == 8) { if ($engine == self::ENGINE_OPENSSL) { $this->cipher_name_openssl_ecb = 'des-ecb'; $this->cipher_name_openssl = 'des-' . $this->_openssl_translate_mode(); @@ -619,18 +616,24 @@ class DES extends Base /** * Sets the key. * - * Keys must be 64-bits long or 8 bytes long. + * Keys can be of any length. DES, itself, uses 64-bit keys (eg. strlen($key) == 8), however, we + * only use the first eight, if $key has more then eight characters in it, and pad $key with the + * null byte if it is less then eight characters long. * * DES also requires that every eighth bit be a parity bit, however, we'll ignore that. * + * If the key is not explicitly set, it'll be assumed to be all zero's. + * * @see \phpseclib\Crypt\Base::setKey() * @access public - * @param string $key + * @param String $key */ function setKey($key) { - 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'); + // We check/cut here only up to max length of the key. + // Key padding to the proper length will be done in _setupKey() + if (strlen($key) > $this->key_size_max) { + $key = substr($key, 0, $this->key_size_max); } // Sets the key @@ -642,10 +645,10 @@ class DES extends Base * * @see \phpseclib\Crypt\Base::_encryptBlock() * @see \phpseclib\Crypt\Base::encrypt() - * @see self::encrypt() + * @see \phpseclib\Crypt\DES::encrypt() * @access private - * @param string $in - * @return string + * @param String $in + * @return String */ function _encryptBlock($in) { @@ -657,10 +660,10 @@ class DES extends Base * * @see \phpseclib\Crypt\Base::_decryptBlock() * @see \phpseclib\Crypt\Base::decrypt() - * @see self::decrypt() + * @see \phpseclib\Crypt\DES::decrypt() * @access private - * @param string $in - * @return string + * @param String $in + * @return String */ function _decryptBlock($in) { @@ -674,12 +677,12 @@ class DES extends Base * {@link http://en.wikipedia.org/wiki/Image:Feistel.png Feistel.png} to get a general * idea of what this function does. * - * @see self::_encryptBlock() - * @see self::_decryptBlock() + * @see \phpseclib\Crypt\DES::_encryptBlock() + * @see \phpseclib\Crypt\DES::_decryptBlock() * @access private - * @param string $block - * @param int $mode - * @return string + * @param String $block + * @param Integer $mode + * @return String */ function _processBlock($block, $mode) { @@ -1307,8 +1310,8 @@ class DES extends Base $des_rounds = $this->des_rounds; // We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function. - // (Currently, for DES, one generated $lambda_function cost on php5.5@32bit ~135kb unfreeable mem and ~230kb on php5.5@64bit) - // (Currently, for TripleDES, one generated $lambda_function cost on php5.5@32bit ~240kb unfreeable mem and ~340kb on php5.5@64bit) + // (Currently, for Crypt_DES, one generated $lambda_function cost on php5.5@32bit ~135kb unfreeable mem and ~230kb on php5.5@64bit) + // (Currently, for Crypt_TripleDES, one generated $lambda_function cost on php5.5@32bit ~240kb unfreeable mem and ~340kb on php5.5@64bit) // After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one $gen_hi_opt_code = (bool)( count($lambda_functions) < 10 ); diff --git a/phpseclib/Crypt/Hash.php b/phpseclib/Crypt/Hash.php index 1b746037..14b8a32a 100644 --- a/phpseclib/Crypt/Hash.php +++ b/phpseclib/Crypt/Hash.php @@ -1,19 +1,26 @@ * setKey('abcdefg'); * @@ -24,9 +31,7 @@ * @category Crypt * @package Hash * @author Jim Wigginton - * @copyright 2015 Jim Wigginton - * @author Andreas Fischer - * @copyright 2015 Andreas Fischer + * @copyright 2007 Jim Wigginton * @license http://www.opensource.org/licenses/mit-license.html MIT License * @link http://phpseclib.sourceforge.net */ @@ -34,39 +39,66 @@ 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 - * @author Andreas Fischer * @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 * - * @see self::setHash() - * @var int + * @see \phpseclib\Crypt\Hash::setHash() + * @var Integer * @access private */ var $hashParam; /** - * Byte-length of hash output (Internal HMAC) + * Byte-length of compression blocks / key (Internal HMAC) * - * @see self::setHash() - * @var int + * @see \phpseclib\Crypt\Hash::setAlgorithm() + * @var Integer * @access private */ - var $length; + var $b; + + /** + * Byte-length of hash output (Internal HMAC) + * + * @see \phpseclib\Crypt\Hash::setHash() + * @var Integer + * @access private + */ + var $l = false; /** * Hash Algorithm * - * @see self::setHash() - * @var string + * @see \phpseclib\Crypt\Hash::setHash() + * @var String * @access private */ var $hash; @@ -74,30 +106,17 @@ class Hash /** * Key * - * @see self::setKey() - * @var string + * @see \phpseclib\Crypt\Hash::setKey() + * @var String * @access private */ var $key = false; - /** - * Initial Hash - * - * Used only for sha512/* - * - * @see self::_sha512() - * @var array - * @access private - */ - var $initial = false; - /** * Outer XOR (Internal HMAC) * - * Used only for sha512/* - * - * @see self::hash() - * @var string + * @see \phpseclib\Crypt\Hash::setKey() + * @var String * @access private */ var $opad; @@ -105,10 +124,8 @@ class Hash /** * Inner XOR (Internal HMAC) * - * Used only for sha512/* - * - * @see self::hash() - * @var string + * @see \phpseclib\Crypt\Hash::setKey() + * @var String * @access private */ var $ipad; @@ -116,15 +133,26 @@ class Hash /** * Default Constructor. * - * @param string $hash + * @param optional String $hash + * @return \phpseclib\Crypt\Hash * @access public */ - function __construct($hash = 'sha256') + function __construct($hash = 'sha1') { - $this->setHash($hash); + 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->ipad = str_repeat(chr(0x36), 128); - $this->opad = str_repeat(chr(0x5C), 128); + $this->setHash($hash); } /** @@ -133,7 +161,7 @@ class Hash * Keys can be of any length. * * @access public - * @param string $key + * @param optional String $key */ function setKey($key = false) { @@ -146,7 +174,7 @@ class Hash * As set by the constructor or by the setHash() method. * * @access public - * @return string + * @return String */ function getHash() { @@ -157,146 +185,405 @@ class Hash * Sets the hash function. * * @access public - * @param string $hash + * @param String $hash */ function setHash($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->length = 12; // 96 / 8 = 12 + $this->l = 12; // 96 / 8 = 12 break; case 'md2': case 'md5': - $this->length = 16; + $this->l = 16; break; case 'sha1': - $this->length = 20; - break; - case 'sha512/224': - $this->length = 28; + $this->l = 20; break; case 'sha256': - case 'sha512/256': - $this->length = 32; + $this->l = 32; break; case 'sha384': - $this->length = 48; + $this->l = 48; break; case 'sha512': - $this->length = 64; + $this->l = 64; + } + + switch ($hash) { + case 'md2': + $mode = CRYPT_HASH_MODE == self::MODE_HASH && in_array('md2', hash_algos()) ? + self::MODE_HASH : self::MODE_INTERNAL; + break; + case 'sha384': + case 'sha512': + $mode = CRYPT_HASH_MODE == self::MODE_MHASH ? self::MODE_INTERNAL : CRYPT_HASH_MODE; break; default: - // 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; + $mode = CRYPT_HASH_MODE; + } + + switch ($mode) { + 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; } - throw new UnsupportedAlgorithmException( - "$hash is not a supported algorithm" - ); + 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'; + } + return; } - 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); - } + switch ($hash) { + case 'md2': + $this->b = 16; + $this->hash = array($this, '_md2'); + break; + case 'md5': + $this->b = 64; + $this->hash = array($this, '_md5'); + break; + case 'sha256': + $this->b = 64; + $this->hash = array($this, '_sha256'); + break; + case 'sha384': + case 'sha512': + $this->b = 128; + $this->hash = array($this, '_sha512'); + break; + case 'sha1': + default: + $this->b = 64; + $this->hash = array($this, '_sha1'); } - $this->hash = $hash; + $this->ipad = str_repeat(chr(0x36), $this->b); + $this->opad = str_repeat(chr(0x5C), $this->b); } /** * Compute the HMAC. * * @access public - * @param string $text - * @return string + * @param String $text + * @return String */ function 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." + $mode = is_array($this->hash) ? self::MODE_INTERNAL : CRYPT_HASH_MODE; - -- http://tools.ietf.org/html/rfc2104#section-2 */ - $key = strlen($this->key) > $this->b ? self::_sha512($this->key, $this->initial) : $this->key; + if (!empty($this->key) || is_string($this->key)) { + switch ($mode) { + case self::MODE_MHASH: + $output = mhash($this->hash, $text, $this->key); + break; + case self::MODE_HASH: + $output = hash_hmac($this->hash, $text, $this->key, true); + break; + case self::MODE_INTERNAL: + /* "Applications that use keys longer than B bytes will first hash the key using H and then use the + resultant L byte string as the actual key to HMAC." - $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 + -- http://tools.ietf.org/html/rfc2104#section-2 */ + $key = strlen($this->key) > $this->b ? call_user_func($this->hash, $this->key) : $this->key; - return substr($output, 0, $this->length); + $key = str_pad($key, $this->b, chr(0)); // step 1 + $temp = $this->ipad ^ $key; // step 2 + $temp .= $text; // step 3 + $temp = call_user_func($this->hash, $temp); // step 4 + $output = $this->opad ^ $key; // step 5 + $output.= $temp; // step 6 + $output = call_user_func($this->hash, $output); // step 7 + } + } else { + switch ($mode) { + case 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); + } } - $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; + return substr($output, 0, $this->l); } /** * Returns the hash length (in bytes) * * @access public - * @return int + * @return Integer */ function getLength() { - return $this->length; + return $this->l; } /** - * Pure-PHP implementation of SHA512 + * Wrapper for MD5 * * @access private - * @param string $m + * @param String $m */ - static function _sha512($m, $hash) + function _md5($m) { - static $k; + 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 , 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; 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( @@ -327,6 +614,8 @@ 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 @@ -340,7 +629,7 @@ class Hash foreach ($chunks as $chunk) { $w = array(); for ($i = 0; $i < 16; $i++) { - $temp = new BigInteger(self::_string_shift($chunk, 8), 256); + $temp = new BigInteger($this->_string_shift($chunk, 8), 256); $temp->setPrecision(64); $w[] = $temp; } @@ -361,21 +650,21 @@ class Hash ); $s1 = $temp[0]->bitwise_xor($temp[1]); $s1 = $s1->bitwise_xor($temp[2]); - $w[$i] = clone $w[$i - 16]; + $w[$i] = $w[$i - 16]->copy(); $w[$i] = $w[$i]->add($s0); $w[$i] = $w[$i]->add($w[$i - 7]); $w[$i] = $w[$i]->add($s1); } // Initialize hash value for this chunk - $a = 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]; + $a = $hash[0]->copy(); + $b = $hash[1]->copy(); + $c = $hash[2]->copy(); + $d = $hash[3]->copy(); + $e = $hash[4]->copy(); + $f = $hash[5]->copy(); + $g = $hash[6]->copy(); + $h = $hash[7]->copy(); // Main loop for ($i = 0; $i < 80; $i++) { @@ -412,13 +701,13 @@ class Hash $t1 = $t1->add($k[$i]); $t1 = $t1->add($w[$i]); - $h = clone $g; - $g = clone $f; - $f = clone $e; + $h = $g->copy(); + $g = $f->copy(); + $f = $e->copy(); $e = $d->add($t1); - $d = clone $c; - $c = clone $b; - $b = clone $a; + $d = $c->copy(); + $c = $b->copy(); + $b = $a->copy(); $a = $t1->add($t2); } @@ -438,22 +727,96 @@ 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() . $hash[6]->toBytes() . $hash[7]->toBytes(); + $hash[4]->toBytes() . $hash[5]->toBytes(); + if ($this->l != 48) { + $temp.= $hash[6]->toBytes() . $hash[7]->toBytes(); + } return $temp; } + /** + * Right Rotate + * + * @access private + * @param Integer $int + * @param Integer $amt + * @see _sha256() + * @return Integer + */ + function _rightRotate($int, $amt) + { + $invamt = 32 - $amt; + $mask = (1 << $invamt) - 1; + return (($int << $invamt) & 0xFFFFFFFF) | (($int >> $amt) & $mask); + } + + /** + * Right Shift + * + * @access private + * @param Integer $int + * @param Integer $amt + * @see _sha256() + * @return Integer + */ + function _rightShift($int, $amt) + { + $mask = (1 << (32 - $amt)) - 1; + return ($int >> $amt) & $mask; + } + + /** + * Not + * + * @access private + * @param Integer $int + * @see _sha256() + * @return Integer + */ + function _not($int) + { + return ~$int & 0xFFFFFFFF; + } + + /** + * Add + * + * _sha256() adds multiple unsigned 32-bit integers. Since PHP doesn't support unsigned integers and since the + * possibility of overflow exists, care has to be taken. BigInteger could be used but this should be faster. + * + * @param Integer $... + * @return Integer + * @see _sha256() + * @access private + */ + function _add() + { + static $mod; + if (!isset($mod)) { + $mod = pow(2, 32); + } + + $result = 0; + $arguments = func_get_args(); + foreach ($arguments as $argument) { + $result+= $argument < 0 ? ($argument & 0x7FFFFFFF) + 0x80000000 : $argument; + } + + return fmod($result, $mod); + } + /** * String Shift * * Inspired by array_shift * - * @param string $string - * @param int $index - * @return string + * @param String $string + * @param optional Integer $index + * @return String * @access private */ - static function _string_shift(&$string, $index = 1) + function _string_shift(&$string, $index = 1) { $substr = substr($string, 0, $index); $string = substr($string, $index); diff --git a/phpseclib/Crypt/RC2.php b/phpseclib/Crypt/RC2.php index 648cf96a..58351759 100644 --- a/phpseclib/Crypt/RC2.php +++ b/phpseclib/Crypt/RC2.php @@ -35,6 +35,8 @@ namespace phpseclib\Crypt; +use phpseclib\Crypt\Base; + /** * Pure-PHP implementation of RC2. * @@ -47,7 +49,7 @@ class RC2 extends Base * Block Length of the cipher * * @see \phpseclib\Crypt\Base::block_size - * @var int + * @var Integer * @access private */ var $block_size = 8; @@ -56,8 +58,8 @@ class RC2 extends Base * The Key * * @see \phpseclib\Crypt\Base::key - * @see self::setKey() - * @var string + * @see setKey() + * @var String * @access private */ var $key; @@ -66,37 +68,29 @@ class RC2 extends Base * The Original (unpadded) Key * * @see \phpseclib\Crypt\Base::key - * @see self::setKey() - * @see self::encrypt() - * @see self::decrypt() - * @var string + * @see setKey() + * @see encrypt() + * @see decrypt() + * @var String * @access private */ var $orig_key; /** - * Don't truncate / null pad key + * The default password key_size used by setPassword() * - * @see \phpseclib\Crypt\Base::_clearBuffers() - * @var bool + * @see \phpseclib\Crypt\Base::password_key_size + * @see \phpseclib\Crypt\Base::setPassword() + * @var Integer * @access private */ - var $skip_key_adjustment = true; - - /** - * Key Length (in bytes) - * - * @see \phpseclib\Crypt\RC2::setKeyLength() - * @var int - * @access private - */ - var $key_length = 16; // = 128 bits + var $password_key_size = 16; // = 128 bits /** * The mcrypt specific name of the cipher * * @see \phpseclib\Crypt\Base::cipher_name_mcrypt - * @var string + * @var String * @access private */ var $cipher_name_mcrypt = 'rc2'; @@ -105,7 +99,7 @@ class RC2 extends Base * Optimizing value while CFB-encrypting * * @see \phpseclib\Crypt\Base::cfb_init_len - * @var int + * @var Integer * @access private */ var $cfb_init_len = 500; @@ -113,9 +107,9 @@ class RC2 extends Base /** * The key length in bits. * - * @see self::setKeyLength() - * @see self::setKey() - * @var int + * @see \phpseclib\Crypt\RC2::setKeyLength() + * @see \phpseclib\Crypt\RC2::setKey() + * @var Integer * @access private * @internal Should be in range [1..1024]. * @internal Changing this value after setting the key has no effect. @@ -125,9 +119,9 @@ class RC2 extends Base /** * The key length in bits. * - * @see self::isValidEnine() - * @see self::setKey() - * @var int + * @see \phpseclib\Crypt\RC2::isValidEnine() + * @see \phpseclib\Crypt\RC2::setKey() + * @var Integer * @access private * @internal Should be in range [1..1024]. */ @@ -136,8 +130,8 @@ class RC2 extends Base /** * The Key Schedule * - * @see self::_setupKey() - * @var array + * @see \phpseclib\Crypt\RC2::_setupKey() + * @var Array * @access private */ var $keys; @@ -146,8 +140,8 @@ class RC2 extends Base * Key expansion randomization table. * Twice the same 256-value sequence to save a modulus in key expansion. * - * @see self::setKey() - * @var array + * @see \phpseclib\Crypt\RC2::setKey() + * @var Array * @access private */ var $pitable = array( @@ -220,8 +214,8 @@ class RC2 extends Base /** * Inverse key expansion randomization table. * - * @see self::setKey() - * @var array + * @see \phpseclib\Crypt\RC2::setKey() + * @var Array * @access private */ var $invpitable = array( @@ -259,37 +253,21 @@ 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 * - * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine() + * This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine() * - * @see \phpseclib\Crypt\Base::__construct() - * @param int $engine + * @see \phpseclib\Crypt\Base::Crypt_Base() + * @param Integer $engine * @access public - * @return bool + * @return Boolean */ function isValidEngine($engine) { switch ($engine) { case self::ENGINE_OPENSSL: - if ($this->current_key_length != 128 || strlen($this->orig_key) < 16) { + if ($this->current_key_length != 128 || strlen($this->orig_key) != 16) { return false; } $this->cipher_name_openssl_ecb = 'rc2-ecb'; @@ -300,40 +278,26 @@ class RC2 extends Base } /** - * Sets the key length. + * Sets the key length * - * Valid key lengths are 8 to 1024. + * Valid key lengths are 1 to 1024. * Calling this function after setting the key has no effect until the next * \phpseclib\Crypt\RC2::setKey() call. * * @access public - * @param int $length in bits - * @throws \LengthException if the key length isn't supported + * @param Integer $length in bits */ function setKeyLength($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'); + if ($length >= 1 && $length <= 1024) { + $this->default_key_length = $length; } - - $this->default_key_length = $this->current_key_length = $length; - } - - /** - * Returns the current key length - * - * @access public - * @return int - */ - function getKeyLength() - { - return $this->current_key_length; } /** * Sets the key. * - * Keys can be of any length. RC2, itself, uses 8 to 1024 bit keys (eg. + * Keys can be of any length. RC2, itself, uses 1 to 1024 bit keys (eg. * strlen($key) <= 128), however, we only use the first 128 bytes if $key * has more then 128 bytes in it, and set $key to a single null byte if * it is empty. @@ -343,22 +307,18 @@ class RC2 extends Base * * @see \phpseclib\Crypt\Base::setKey() * @access public - * @param string $key - * @param int $t1 optional Effective key length in bits. - * @throws \LengthException if the key length isn't supported + * @param String $key + * @param Integer $t1 optional Effective key length in bits. */ - function setKey($key, $t1 = false) + function setKey($key, $t1 = 0) { $this->orig_key = $key; - if ($t1 === false) { + if ($t1 <= 0) { $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"; @@ -389,19 +349,18 @@ class RC2 extends Base // Prepare the key for mcrypt. $l[0] = $this->invpitable[$l[0]]; array_unshift($l, 'C*'); - parent::setKey(call_user_func_array('pack', $l)); } /** * Encrypts a message. * - * Mostly a wrapper for \phpseclib\Crypt\Base::encrypt, with some additional OpenSSL handling code + * Mostly a wrapper for Crypt_Base::encrypt, with some additional OpenSSL handling code * - * @see self::decrypt() + * @see decrypt() * @access public - * @param string $plaintext - * @return string $ciphertext + * @param String $plaintext + * @return String $ciphertext */ function encrypt($plaintext) { @@ -419,12 +378,12 @@ class RC2 extends Base /** * Decrypts a message. * - * Mostly a wrapper for \phpseclib\Crypt\Base::decrypt, with some additional OpenSSL handling code + * Mostly a wrapper for Crypt_Base::decrypt, with some additional OpenSSL handling code * - * @see self::encrypt() + * @see encrypt() * @access public - * @param string $ciphertext - * @return string $plaintext + * @param String $ciphertext + * @return String $plaintext */ function decrypt($ciphertext) { @@ -436,7 +395,7 @@ class RC2 extends Base return $result; } - return parent::decrypt($ciphertext); + return parent::encrypt($ciphertext); } /** @@ -445,8 +404,8 @@ class RC2 extends Base * @see \phpseclib\Crypt\Base::_encryptBlock() * @see \phpseclib\Crypt\Base::encrypt() * @access private - * @param string $in - * @return string + * @param String $in + * @return String */ function _encryptBlock($in) { @@ -490,8 +449,8 @@ class RC2 extends Base * @see \phpseclib\Crypt\Base::_decryptBlock() * @see \phpseclib\Crypt\Base::decrypt() * @access private - * @param string $in - * @return string + * @param String $in + * @return String */ function _decryptBlock($in) { @@ -579,7 +538,7 @@ class RC2 extends Base // for the mixing rounds, for better inline crypt performance [~20% faster]. // But for memory reason we have to limit those ultra-optimized $lambda_functions to an amount of 10. // (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); + $gen_hi_opt_code = (bool)( count($lambda_functions) < 10 ); // Generation of a uniqe hash for our generated code $code_hash = "Crypt_RC2, {$this->mode}"; diff --git a/phpseclib/Crypt/RC4.php b/phpseclib/Crypt/RC4.php index 3da70b6e..2c7f74c2 100644 --- a/phpseclib/Crypt/RC4.php +++ b/phpseclib/Crypt/RC4.php @@ -44,6 +44,8 @@ namespace phpseclib\Crypt; +use phpseclib\Crypt\Base; + /** * Pure-PHP implementation of RC4. * @@ -68,25 +70,26 @@ class RC4 extends Base * so we the block_size to 0 * * @see \phpseclib\Crypt\Base::block_size - * @var int + * @var Integer * @access private */ var $block_size = 0; /** - * Key Length (in bytes) + * The default password key_size used by setPassword() * - * @see \phpseclib\Crypt\RC4::setKeyLength() - * @var int + * @see \phpseclib\Crypt\Base::password_key_size + * @see \phpseclib\Crypt\Base::setPassword() + * @var Integer * @access private */ - var $key_length = 128; // = 1024 bits + var $password_key_size = 128; // = 1024 bits /** * The mcrypt specific name of the cipher * * @see \phpseclib\Crypt\Base::cipher_name_mcrypt - * @var string + * @var String * @access private */ var $cipher_name_mcrypt = 'arcfour'; @@ -103,8 +106,8 @@ class RC4 extends Base /** * The Key * - * @see self::setKey() - * @var string + * @see \phpseclib\Crypt\RC4::setKey() + * @var String * @access private */ var $key = "\0"; @@ -112,8 +115,8 @@ class RC4 extends Base /** * The Key Stream for decryption and encryption * - * @see self::setKey() - * @var array + * @see \phpseclib\Crypt\RC4::setKey() + * @var Array * @access private */ var $stream; @@ -121,6 +124,8 @@ 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 @@ -133,12 +138,12 @@ class RC4 extends Base /** * Test for engine validity * - * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine() + * This is mainly just a wrapper to set things up for Crypt_Base::isValidEngine() * - * @see \phpseclib\Crypt\Base::__construct() - * @param int $engine + * @see Crypt_Base::Crypt_Base() + * @param Integer $engine * @access public - * @return bool + * @return Boolean */ function isValidEngine($engine) { @@ -163,63 +168,51 @@ class RC4 extends Base } /** - * RC4 does not use an IV + * Dummy function. * + * Some protocols, such as WEP, prepend an "initialization vector" to the key, effectively creating a new key [1]. + * If you need to use an initialization vector in this manner, feel free to prepend it to the key, yourself, before + * calling setKey(). + * + * [1] WEP's initialization vectors (IV's) are used in a somewhat insecure way. Since, in that protocol, + * the IV's are relatively easy to predict, an attack described by + * {@link http://www.drizzle.com/~aboba/IEEE/rc4_ksaproc.pdf Scott Fluhrer, Itsik Mantin, and Adi Shamir} + * can be used to quickly guess at the rest of the key. The following links elaborate: + * + * {@link http://www.rsa.com/rsalabs/node.asp?id=2009 http://www.rsa.com/rsalabs/node.asp?id=2009} + * {@link http://en.wikipedia.org/wiki/Related_key_attack http://en.wikipedia.org/wiki/Related_key_attack} + * + * @param String $iv + * @see \phpseclib\Crypt\RC4::setKey() * @access public - * @return bool */ - function usesIV() + function setIV($iv) { - return false; } /** - * Sets the key length + * Sets the key. * - * Keys can be between 1 and 256 bytes long. + * Keys can be between 1 and 256 bytes long. If they are longer then 256 bytes, the first 256 bytes will + * be used. If no key is explicitly set, it'll be assumed to be a single null byte. * * @access public - * @param int $length - * @throws \LengthException if the key length is invalid - */ - function setKeyLength($length) - { - 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 + * @see \phpseclib\Crypt\Base::setKey() + * @param String $key */ 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); + parent::setKey(substr($key, 0, 256)); } /** * Encrypts a message. * * @see \phpseclib\Crypt\Base::decrypt() - * @see self::_crypt() + * @see \phpseclib\Crypt\RC4::_crypt() * @access public - * @param string $plaintext - * @return string $ciphertext + * @param String $plaintext + * @return String $ciphertext */ function encrypt($plaintext) { @@ -236,10 +229,10 @@ class RC4 extends Base * At least if the continuous buffer is disabled. * * @see \phpseclib\Crypt\Base::encrypt() - * @see self::_crypt() + * @see \phpseclib\Crypt\RC4::_crypt() * @access public - * @param string $ciphertext - * @return string $plaintext + * @param String $ciphertext + * @return String $plaintext */ function decrypt($ciphertext) { @@ -253,7 +246,7 @@ class RC4 extends Base * Encrypts a block * * @access private - * @param string $in + * @param String $in */ function _encryptBlock($in) { @@ -264,7 +257,7 @@ class RC4 extends Base * Decrypts a block * * @access private - * @param string $in + * @param String $in */ function _decryptBlock($in) { @@ -301,12 +294,12 @@ class RC4 extends Base /** * Encrypts or decrypts a message. * - * @see self::encrypt() - * @see self::decrypt() + * @see \phpseclib\Crypt\RC4::encrypt() + * @see \phpseclib\Crypt\RC4::decrypt() * @access private - * @param string $text - * @param int $mode - * @return string $text + * @param String $text + * @param Integer $mode + * @return String $text */ function _crypt($text, $mode) { diff --git a/phpseclib/Crypt/RSA.php b/phpseclib/Crypt/RSA.php index 73636816..238f30cd 100644 --- a/phpseclib/Crypt/RSA.php +++ b/phpseclib/Crypt/RSA.php @@ -8,30 +8,36 @@ * Here's an example of how to encrypt and decrypt text with this library: * * createKey()); * - * $plaintext = 'terrafrost'; + * $plaintext = 'terrafrost'; * - * $ciphertext = $publickey->encrypt($plaintext); + * $rsa->loadKey($privatekey); + * $ciphertext = $rsa->encrypt($plaintext); * - * echo $privatekey->decrypt($ciphertext); + * $rsa->loadKey($publickey); + * echo $rsa->decrypt($ciphertext); * ?> * * * Here's an example of how to create signatures and verify signatures with this library: * * createKey()); * - * $plaintext = 'terrafrost'; + * $plaintext = 'terrafrost'; * - * $signature = $privatekey->sign($plaintext); + * $rsa->loadKey($privatekey); + * $signature = $rsa->sign($plaintext); * - * echo $publickey->verify($plaintext, $signature) ? 'verified' : 'unverified'; + * $rsa->loadKey($publickey); + * echo $rsa->verify($plaintext, $signature) ? 'verified' : 'unverified'; * ?> * * @@ -45,7 +51,13 @@ namespace phpseclib\Crypt; -use phpseclib\File\ASN1; +use phpseclib\Crypt\AES; +use phpseclib\Crypt\Base; +use phpseclib\Crypt\DES; +use phpseclib\Crypt\Hash; +use phpseclib\Crypt\Random; +use phpseclib\Crypt\RSA; +use phpseclib\Crypt\TripleDES; use phpseclib\Math\BigInteger; /** @@ -59,136 +71,215 @@ class RSA { /**#@+ * @access public - * @see self::encrypt() - * @see self::decrypt() + * @see \phpseclib\Crypt\RSA::encrypt() + * @see \phpseclib\Crypt\RSA::decrypt() */ /** * Use {@link http://en.wikipedia.org/wiki/Optimal_Asymmetric_Encryption_Padding Optimal Asymmetric Encryption Padding} * (OAEP) for encryption / decryption. * - * Uses sha256 by default + * Uses sha1 by default. * - * @see self::setHash() - * @see self::setMGFHash() + * @see \phpseclib\Crypt\RSA::setHash() + * @see \phpseclib\Crypt\RSA::setMGFHash() */ - const PADDING_OAEP = 1; + const ENCRYPTION_OAEP = 1; /** * Use PKCS#1 padding. * - * Although self::PADDING_OAEP / self::PADDING_PSS offers more security, including PKCS#1 padding is necessary for purposes of backwards + * Although self::ENCRYPTION_OAEP offers more security, including PKCS#1 padding is necessary for purposes of backwards * compatibility with protocols (like SSH-1) written before OAEP's introduction. - */ - const PADDING_PKCS1 = 2; + */ + const ENCRYPTION_PKCS1 = 2; /** * Do not use any padding * * Although this method is not recommended it can none-the-less sometimes be useful if you're trying to decrypt some legacy * stuff, if you're trying to diagnose why an encrypted message isn't decrypting, etc. */ - const PADDING_NONE = 3; - /** - * Use PKCS#1 padding with PKCS1 v1.5 compatability - * - * A PKCS1 v2.1 encrypted message may not successfully decrypt with a PKCS1 v1.5 implementation (such as OpenSSL). - */ - const PADDING_PKCS15_COMPAT = 6; + const ENCRYPTION_NONE = 3; /**#@-*/ /**#@+ * @access public - * @see self::sign() - * @see self::verify() - * @see self::setHash() - */ + * @see \phpseclib\Crypt\RSA::sign() + * @see \phpseclib\Crypt\RSA::verify() + * @see \phpseclib\Crypt\RSA::setHash() + */ /** * Use the Probabilistic Signature Scheme for signing * - * Uses sha256 and 0 as the salt length + * Uses sha1 by default. * - * @see self::setSaltLength() - * @see self::setMGFHash() - * @see self::setHash() - */ - const PADDING_PSS = 4; + * @see \phpseclib\Crypt\RSA::setSaltLength() + * @see \phpseclib\Crypt\RSA::setMGFHash() + */ + const SIGNATURE_PSS = 1; /** - * Use a relaxed version of PKCS#1 padding for signature verification - */ - const PADDING_RELAXED_PKCS1 = 5; + * Use the PKCS#1 scheme by default. + * + * Although self::SIGNATURE_PSS offers more security, including PKCS#1 signing is necessary for purposes of backwards + * compatibility with protocols (like SSH-2) written before PSS's introduction. + */ + const SIGNATURE_PKCS1 = 2; /**#@-*/ /**#@+ * @access private - * @see self::createKey() - */ + * @see \phpseclib\Crypt\RSA::createKey() + */ /** * ASN1 Integer - */ + */ const ASN1_INTEGER = 2; /** * ASN1 Bit String - */ + */ const ASN1_BITSTRING = 3; /** * ASN1 Octet String - */ + */ const ASN1_OCTETSTRING = 4; /** * ASN1 Object Identifier - */ + */ const ASN1_OBJECT = 6; /** * ASN1 Sequence (with the constucted bit set) - */ + */ const ASN1_SEQUENCE = 48; /**#@-*/ /**#@+ * @access private - * @see self::__construct() - */ + * @see \phpseclib\Crypt\RSA::__construct() + */ /** * To use the pure-PHP implementation - */ + */ const MODE_INTERNAL = 1; /** * To use the OpenSSL library * * (if enabled; otherwise, the internal implementation will be used) - */ + */ const MODE_OPENSSL = 2; /**#@-*/ + /**#@+ + * @access public + * @see \phpseclib\Crypt\RSA::createKey() + * @see \phpseclib\Crypt\RSA::setPrivateKeyFormat() + */ + /** + * PKCS#1 formatted private key + * + * Used by OpenSSH + */ + const PRIVATE_FORMAT_PKCS1 = 0; + /** + * PuTTY formatted private key + */ + const PRIVATE_FORMAT_PUTTY = 1; + /** + * XML formatted private key + */ + const PRIVATE_FORMAT_XML = 2; + /** + * PKCS#8 formatted private key + */ + const PRIVATE_FORMAT_PKCS8 = 3; + /**#@-*/ + + /**#@+ + * @access public + * @see \phpseclib\Crypt\RSA::createKey() + * @see \phpseclib\Crypt\RSA::setPublicKeyFormat() + */ + /** + * Raw public key + * + * An array containing two \phpseclib\Math\BigInteger objects. + * + * The exponent can be indexed with any of the following: + * + * 0, e, exponent, publicExponent + * + * The modulus can be indexed with any of the following: + * + * 1, n, modulo, modulus + */ + const PUBLIC_FORMAT_RAW = 3; + /** + * PKCS#1 formatted public key (raw) + * + * Used by File/X509.php + * + * Has the following header: + * + * -----BEGIN RSA PUBLIC KEY----- + * + * Analogous to ssh-keygen's pem format (as specified by -m) + */ + const PUBLIC_FORMAT_PKCS1 = 4; + const PUBLIC_FORMAT_PKCS1_RAW = 4; + /** + * XML formatted public key + */ + const PUBLIC_FORMAT_XML = 5; + /** + * OpenSSH formatted public key + * + * Place in $HOME/.ssh/authorized_keys + */ + const PUBLIC_FORMAT_OPENSSH = 6; + /** + * PKCS#1 formatted public key (encapsulated) + * + * Used by PHP's openssl_public_encrypt() and openssl's rsautl (when -pubin is set) + * + * Has the following header: + * + * -----BEGIN PUBLIC KEY----- + * + * Analogous to ssh-keygen's pkcs8 format (as specified by -m). Although PKCS8 + * is specific to private keys it's basically creating a DER-encoded wrapper + * for keys. This just extends that same concept to public keys (much like ssh-keygen) + */ + const PUBLIC_FORMAT_PKCS8 = 7; + /**#@-*/ + /** * Precomputed Zero * - * @var array + * @var Array * @access private */ - static $zero; + var $zero; /** * Precomputed One * - * @var array + * @var Array * @access private */ - static $one; + var $one; /** * Private Key Format * - * @var string + * @var Integer * @access private */ - var $privateKeyFormat = 'PKCS1'; + var $privateKeyFormat = self::PRIVATE_FORMAT_PKCS1; /** * Public Key Format * - * @var string - * @access private + * @var Integer + * @access public */ - var $publicKeyFormat = 'PKCS8'; + var $publicKeyFormat = self::PUBLIC_FORMAT_PKCS8; /** * Modulus (ie. n) @@ -217,7 +308,7 @@ class RSA /** * Primes for Chinese Remainder Theorem (ie. p and q) * - * @var array + * @var Array * @access private */ var $primes; @@ -225,7 +316,7 @@ class RSA /** * Exponents for Chinese Remainder Theorem (ie. dP and dQ) * - * @var array + * @var Array * @access private */ var $exponents; @@ -233,7 +324,7 @@ class RSA /** * Coefficients for Chinese Remainder Theorem (ie. qInv) * - * @var array + * @var Array * @access private */ var $coefficients; @@ -241,7 +332,7 @@ class RSA /** * Hash name * - * @var string + * @var String * @access private */ var $hashName; @@ -257,7 +348,7 @@ class RSA /** * Length of hash function output * - * @var int + * @var Integer * @access private */ var $hLen; @@ -265,7 +356,7 @@ class RSA /** * Length of salt * - * @var int + * @var Integer * @access private */ var $sLen; @@ -281,15 +372,31 @@ class RSA /** * Length of MGF hash function output * - * @var int + * @var Integer * @access private */ var $mgfHLen; + /** + * Encryption mode + * + * @var Integer + * @access private + */ + var $encryptionMode = self::ENCRYPTION_OAEP; + + /** + * Signature mode + * + * @var Integer + * @access private + */ + var $signatureMode = self::SIGNATURE_PSS; + /** * Public Exponent * - * @var mixed + * @var Mixed * @access private */ var $publicExponent = false; @@ -297,75 +404,52 @@ class RSA /** * Password * - * @var string + * @var String * @access private */ var $password = false; /** - * Loaded File Format + * Components * - * @var string + * For use with parsing XML formatted keys. PHP's XML Parser functions use utilized - instead of PHP's DOM functions - + * because PHP's XML Parser functions work on PHP4 whereas PHP's DOM functions - although surperior - don't. + * + * @see \phpseclib\Crypt\RSA::_start_element_handler() + * @var Array * @access private */ - var $format = false; + var $components = array(); + + /** + * Current String + * + * For use with parsing XML formatted keys. + * + * @see \phpseclib\Crypt\RSA::_character_handler() + * @see \phpseclib\Crypt\RSA::_stop_element_handler() + * @var Mixed + * @access private + */ + var $current; /** * OpenSSL configuration file name. * * Set to null to use system configuration file. - * - * @see self::createKey() - * @var mixed - * @access public + * @see \phpseclib\Crypt\RSA::createKey() + * @var Mixed + * @Access public */ - static $configFile; + var $configFile; /** - * Supported file formats (lower case) + * Public key comment field. * - * @see self::_initialize_static_variables() - * @var array + * @var String * @access private */ - static $fileFormats = false; - - /** - * Supported file formats (original case) - * - * @see self::_initialize_static_variables() - * @var array - * @access private - */ - static $origFileFormats = false; - - - /** - * Initialize static variables - * - * @access private - */ - static function _initialize_static_variables() - { - if (!isset(self::$zero)) { - self::$zero= new BigInteger(0); - self::$one = new BigInteger(1); - self::$configFile = __DIR__ . '/../openssl.cnf'; - - if (self::$fileFormats === false) { - self::$fileFormats = array(); - foreach (glob(__DIR__ . '/RSA/*.php') as $file) { - $name = pathinfo($file, PATHINFO_FILENAME); - $type = 'phpseclib\Crypt\RSA\\' . $name; - $meta = new \ReflectionClass($type); - if (!$meta->isAbstract()) { - self::$fileFormats[strtolower($name)] = $type; - self::$origFileFormats[] = $name; - } - } - } - } - } + var $comment = 'phpseclib-generated-key'; /** * The constructor @@ -379,32 +463,7 @@ class RSA */ function __construct() { - self::_initialize_static_variables(); - - $this->hash = new Hash('sha256'); - $this->hLen = $this->hash->getLength(); - $this->hashName = 'sha256'; - $this->mgfHash = new Hash('sha256'); - $this->mgfHLen = $this->mgfHash->getLength(); - } - - /** - * Create public / private key pair - * - * Returns an array with the following three elements: - * - 'privatekey': The private key. - * - 'publickey': The public key. - * - 'partialkey': A partially computed key (if the execution time exceeded $timeout). - * Will need to be passed back to \phpseclib\Crypt\RSA::createKey() as the third parameter for further processing. - * - * @access public - * @param int $bits - * @param int $timeout - * @param array $p - */ - static function createKey($bits = 2048, $timeout = false, $partial = array()) - { - self::_initialize_static_variables(); + $this->configFile = dirname(__FILE__) . '/../openssl.cnf'; if (!defined('CRYPT_RSA_MODE')) { switch (true) { @@ -414,7 +473,11 @@ class RSA case defined('MATH_BIGINTEGER_OPENSSL_DISABLE'): define('CRYPT_RSA_MODE', self::MODE_INTERNAL); break; - case extension_loaded('openssl') && file_exists(self::$configFile): + // openssl_pkey_get_details - which is used in the only place Crypt/RSA.php uses OpenSSL - was introduced in PHP 5.2.0 + case !function_exists('openssl_pkey_get_details'): + define('CRYPT_RSA_MODE', self::MODE_INTERNAL); + break; + case extension_loaded('openssl') && version_compare(PHP_VERSION, '4.2.0', '>=') && file_exists($this->configFile): // some versions of XAMPP have mismatched versions of OpenSSL which causes it not to work ob_start(); @phpinfo(); @@ -454,6 +517,32 @@ class RSA } } + $this->zero = new BigInteger(); + $this->one = new BigInteger(1); + + $this->hash = new Hash('sha1'); + $this->hLen = $this->hash->getLength(); + $this->hashName = 'sha1'; + $this->mgfHash = new Hash('sha1'); + $this->mgfHLen = $this->mgfHash->getLength(); + } + + /** + * Create public / private key pair + * + * Returns an array with the following three elements: + * - 'privatekey': The private key. + * - 'publickey': The public key. + * - 'partialkey': A partially computed key (if the execution time exceeded $timeout). + * Will need to be passed back to \phpseclib\Crypt\RSA::createKey() as the third parameter for further processing. + * + * @access public + * @param optional Integer $bits + * @param optional Integer $timeout + * @param optional array $p + */ + function createKey($bits = 1024, $timeout = false, $partial = array()) + { if (!defined('CRYPT_RSA_EXPONENT')) { // http://en.wikipedia.org/wiki/65537_%28number%29 define('CRYPT_RSA_EXPONENT', '65537'); @@ -471,17 +560,16 @@ class RSA // OpenSSL uses 65537 as the exponent and requires RSA keys be 384 bits minimum if (CRYPT_RSA_MODE == self::MODE_OPENSSL && $bits >= 384 && CRYPT_RSA_EXPONENT == 65537) { $config = array(); - if (isset(self::$configFile)) { - $config['config'] = self::$configFile; + if (isset($this->configFile)) { + $config['config'] = $this->configFile; } $rsa = openssl_pkey_new(array('private_key_bits' => $bits) + $config); - openssl_pkey_export($rsa, $privatekeystr, null, $config); - $privatekey = new RSA(); - $privatekey->load($privatekeystr); + openssl_pkey_export($rsa, $privatekey, null, $config); + $publickey = openssl_pkey_get_details($rsa); + $publickey = $publickey['key']; - $publickeyarr = openssl_pkey_get_details($rsa); - $publickey = new RSA(); - $publickey->load($publickeyarr['key']); + $privatekey = call_user_func_array(array($this, '_convertPrivateKey'), array_values($this->_parseKey($privatekey, self::PRIVATE_FORMAT_PKCS1))); + $publickey = call_user_func_array(array($this, '_convertPublicKey'), array_values($this->_parseKey($publickey, self::PUBLIC_FORMAT_PKCS1))); // clear the buffer of error strings stemming from a minimalistic openssl.cnf while (openssl_error_string() !== false) { @@ -499,7 +587,7 @@ class RSA $e = new BigInteger(CRYPT_RSA_EXPONENT); } - extract(self::_generateMinMax($bits)); + extract($this->_generateMinMax($bits)); $absoluteMin = $min; $temp = $bits >> 1; // divide by two to see how many bits P and Q would be if ($temp > CRYPT_RSA_SMALLEST_PRIME) { @@ -508,17 +596,19 @@ class RSA } else { $num_primes = 2; } - extract(self::_generateMinMax($temp + $bits % $temp)); + extract($this->_generateMinMax($temp + $bits % $temp)); $finalMax = $max; - extract(self::_generateMinMax($temp)); + extract($this->_generateMinMax($temp)); - $n = clone self::$one; + $generator = new BigInteger(); + + $n = $this->one->copy(); if (!empty($partial)) { extract(unserialize($partial)); } else { $exponents = $coefficients = $primes = array(); $lcm = array( - 'top' => clone self::$one, + 'top' => $this->one->copy(), 'bottom' => false ); } @@ -547,12 +637,12 @@ class RSA if ($i == $num_primes) { list($min, $temp) = $absoluteMin->divide($n); - if (!$temp->equals(self::$zero)) { - $min = $min->add(self::$one); // ie. ceil() + if (!$temp->equals($this->zero)) { + $min = $min->add($this->one); // ie. ceil() } - $primes[$i] = BigInteger::randomPrime($min, $finalMax, $timeout); + $primes[$i] = $generator->randomPrime($min, $finalMax, $timeout); } else { - $primes[$i] = BigInteger::randomPrime($min, $max, $timeout); + $primes[$i] = $generator->randomPrime($min, $max, $timeout); } if ($primes[$i] === false) { // if we've reached the timeout @@ -569,8 +659,8 @@ class RSA } return array( - 'privatekey' => false, - 'publickey' => false, + 'privatekey' => '', + 'publickey' => '', 'partialkey' => $partialkey ); } @@ -583,7 +673,7 @@ class RSA $n = $n->multiply($primes[$i]); - $temp = $primes[$i]->subtract(self::$one); + $temp = $primes[$i]->subtract($this->one); // textbook RSA implementations use Euler's totient function instead of the least common multiple. // see http://en.wikipedia.org/wiki/Euler%27s_totient_function @@ -596,7 +686,7 @@ class RSA list($temp) = $lcm['top']->divide($lcm['bottom']); $gcd = $temp->gcd($e); $i0 = 1; - } while (!$gcd->equals(self::$one)); + } while (!$gcd->equals($this->one)); $d = $e->modInverse($temp); @@ -615,62 +705,804 @@ class RSA // coefficient INTEGER, -- (inverse of q) mod p // otherPrimeInfos OtherPrimeInfos OPTIONAL // } - $privatekey = new RSA(); - $privatekey->modulus = $n; - $privatekey->k = $bits >> 3; - $privatekey->publicExponent = $e; - $privatekey->exponent = $d; - $privatekey->privateExponent = $e; - $privatekey->primes = $primes; - $privatekey->exponents = $exponents; - $privatekey->coefficients = $coefficients; - - $publickey = new RSA(); - $publickey->modulus = $n; - $publickey->k = $bits >> 3; - $publickey->exponent = $e; return array( - 'privatekey' => $privatekey, - 'publickey' => $publickey, + 'privatekey' => $this->_convertPrivateKey($n, $e, $d, $primes, $exponents, $coefficients), + 'publickey' => $this->_convertPublicKey($n, $e), 'partialkey' => false ); } /** - * Add a fileformat plugin + * Convert a private key to the appropriate format. * - * The plugin needs to either already be loaded or be auto-loadable. - * Loading a plugin whose shortname overwrite an existing shortname will overwrite the old plugin. - * - * @see self::load() - * @param string $fullname - * @access public - * @return bool + * @access private + * @see setPrivateKeyFormat() + * @param String $RSAPrivateKey + * @return String */ - static function addFileFormat($fullname) + function _convertPrivateKey($n, $e, $d, $primes, $exponents, $coefficients) { - self::_initialize_static_variables(); + $signed = $this->privateKeyFormat != self::PRIVATE_FORMAT_XML; + $num_primes = count($primes); + $raw = array( + 'version' => $num_primes == 2 ? chr(0) : chr(1), // two-prime vs. multi + 'modulus' => $n->toBytes($signed), + 'publicExponent' => $e->toBytes($signed), + 'privateExponent' => $d->toBytes($signed), + 'prime1' => $primes[1]->toBytes($signed), + 'prime2' => $primes[2]->toBytes($signed), + 'exponent1' => $exponents[1]->toBytes($signed), + 'exponent2' => $exponents[2]->toBytes($signed), + 'coefficient' => $coefficients[2]->toBytes($signed) + ); - if (class_exists($fullname)) { - $meta = new \ReflectionClass($path); - $shortname = $meta->getShortName(); - self::$fileFormats[strtolower($shortname)] = $fullname; - self::$origFileFormats[] = $shortname; + // if the format in question does not support multi-prime rsa and multi-prime rsa was used, + // call _convertPublicKey() instead. + switch ($this->privateKeyFormat) { + case self::PRIVATE_FORMAT_XML: + if ($num_primes != 2) { + return false; + } + return "\r\n" . + ' ' . base64_encode($raw['modulus']) . "\r\n" . + ' ' . base64_encode($raw['publicExponent']) . "\r\n" . + '

' . base64_encode($raw['prime1']) . "

\r\n" . + ' ' . base64_encode($raw['prime2']) . "\r\n" . + ' ' . base64_encode($raw['exponent1']) . "\r\n" . + ' ' . base64_encode($raw['exponent2']) . "\r\n" . + ' ' . base64_encode($raw['coefficient']) . "\r\n" . + ' ' . base64_encode($raw['privateExponent']) . "\r\n" . + '
'; + break; + case self::PRIVATE_FORMAT_PUTTY: + if ($num_primes != 2) { + return false; + } + $key = "PuTTY-User-Key-File-2: ssh-rsa\r\nEncryption: "; + $encryption = (!empty($this->password) || is_string($this->password)) ? 'aes256-cbc' : 'none'; + $key.= $encryption; + $key.= "\r\nComment: " . $this->comment . "\r\n"; + $public = pack( + 'Na*Na*Na*', + strlen('ssh-rsa'), + 'ssh-rsa', + strlen($raw['publicExponent']), + $raw['publicExponent'], + strlen($raw['modulus']), + $raw['modulus'] + ); + $source = pack( + 'Na*Na*Na*Na*', + strlen('ssh-rsa'), + 'ssh-rsa', + strlen($encryption), + $encryption, + strlen($this->comment), + $this->comment, + strlen($public), + $public + ); + $public = base64_encode($public); + $key.= "Public-Lines: " . ((strlen($public) + 63) >> 6) . "\r\n"; + $key.= chunk_split($public, 64); + $private = pack( + 'Na*Na*Na*Na*', + strlen($raw['privateExponent']), + $raw['privateExponent'], + strlen($raw['prime1']), + $raw['prime1'], + strlen($raw['prime2']), + $raw['prime2'], + strlen($raw['coefficient']), + $raw['coefficient'] + ); + if (empty($this->password) && !is_string($this->password)) { + $source.= pack('Na*', strlen($private), $private); + $hashkey = 'putty-private-key-file-mac-key'; + } else { + $private.= Random::string(16 - (strlen($private) & 15)); + $source.= pack('Na*', strlen($private), $private); + $sequence = 0; + $symkey = ''; + while (strlen($symkey) < 32) { + $temp = pack('Na*', $sequence++, $this->password); + $symkey.= pack('H*', sha1($temp)); + } + $symkey = substr($symkey, 0, 32); + $crypto = new AES(); + + $crypto->setKey($symkey); + $crypto->disablePadding(); + $private = $crypto->encrypt($private); + $hashkey = 'putty-private-key-file-mac-key' . $this->password; + } + + $private = base64_encode($private); + $key.= 'Private-Lines: ' . ((strlen($private) + 63) >> 6) . "\r\n"; + $key.= chunk_split($private, 64); + $hash = new Hash('sha1'); + $hash->setKey(pack('H*', sha1($hashkey))); + $key.= 'Private-MAC: ' . bin2hex($hash->hash($source)) . "\r\n"; + + return $key; + default: // eg. self::PRIVATE_FORMAT_PKCS1 + $components = array(); + foreach ($raw as $name => $value) { + $components[$name] = pack('Ca*a*', self::ASN1_INTEGER, $this->_encodeLength(strlen($value)), $value); + } + + $RSAPrivateKey = implode('', $components); + + if ($num_primes > 2) { + $OtherPrimeInfos = ''; + for ($i = 3; $i <= $num_primes; $i++) { + // OtherPrimeInfos ::= SEQUENCE SIZE(1..MAX) OF OtherPrimeInfo + // + // OtherPrimeInfo ::= SEQUENCE { + // prime INTEGER, -- ri + // exponent INTEGER, -- di + // coefficient INTEGER -- ti + // } + $OtherPrimeInfo = pack('Ca*a*', self::ASN1_INTEGER, $this->_encodeLength(strlen($primes[$i]->toBytes(true))), $primes[$i]->toBytes(true)); + $OtherPrimeInfo.= pack('Ca*a*', self::ASN1_INTEGER, $this->_encodeLength(strlen($exponents[$i]->toBytes(true))), $exponents[$i]->toBytes(true)); + $OtherPrimeInfo.= pack('Ca*a*', self::ASN1_INTEGER, $this->_encodeLength(strlen($coefficients[$i]->toBytes(true))), $coefficients[$i]->toBytes(true)); + $OtherPrimeInfos.= pack('Ca*a*', self::ASN1_SEQUENCE, $this->_encodeLength(strlen($OtherPrimeInfo)), $OtherPrimeInfo); + } + $RSAPrivateKey.= pack('Ca*a*', self::ASN1_SEQUENCE, $this->_encodeLength(strlen($OtherPrimeInfos)), $OtherPrimeInfos); + } + + $RSAPrivateKey = pack('Ca*a*', self::ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey); + + if ($this->privateKeyFormat == self::PRIVATE_FORMAT_PKCS8) { + $rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA + $RSAPrivateKey = pack( + 'Ca*a*Ca*a*', + self::ASN1_INTEGER, + "\01\00", + $rsaOID, + 4, + $this->_encodeLength(strlen($RSAPrivateKey)), + $RSAPrivateKey + ); + $RSAPrivateKey = pack('Ca*a*', self::ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey); + if (!empty($this->password) || is_string($this->password)) { + $salt = Random::string(8); + $iterationCount = 2048; + + $crypto = new DES(); + $crypto->setPassword($this->password, 'pbkdf1', 'md5', $salt, $iterationCount); + $RSAPrivateKey = $crypto->encrypt($RSAPrivateKey); + + $parameters = pack( + 'Ca*a*Ca*N', + self::ASN1_OCTETSTRING, + $this->_encodeLength(strlen($salt)), + $salt, + self::ASN1_INTEGER, + $this->_encodeLength(4), + $iterationCount + ); + $pbeWithMD5AndDES_CBC = "\x2a\x86\x48\x86\xf7\x0d\x01\x05\x03"; + + $encryptionAlgorithm = pack( + 'Ca*a*Ca*a*', + self::ASN1_OBJECT, + $this->_encodeLength(strlen($pbeWithMD5AndDES_CBC)), + $pbeWithMD5AndDES_CBC, + self::ASN1_SEQUENCE, + $this->_encodeLength(strlen($parameters)), + $parameters + ); + + $RSAPrivateKey = pack( + 'Ca*a*Ca*a*', + self::ASN1_SEQUENCE, + $this->_encodeLength(strlen($encryptionAlgorithm)), + $encryptionAlgorithm, + self::ASN1_OCTETSTRING, + $this->_encodeLength(strlen($RSAPrivateKey)), + $RSAPrivateKey + ); + + $RSAPrivateKey = pack('Ca*a*', self::ASN1_SEQUENCE, $this->_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey); + + $RSAPrivateKey = "-----BEGIN ENCRYPTED PRIVATE KEY-----\r\n" . + chunk_split(base64_encode($RSAPrivateKey), 64) . + '-----END ENCRYPTED PRIVATE KEY-----'; + } else { + $RSAPrivateKey = "-----BEGIN PRIVATE KEY-----\r\n" . + chunk_split(base64_encode($RSAPrivateKey), 64) . + '-----END PRIVATE KEY-----'; + } + return $RSAPrivateKey; + } + + if (!empty($this->password) || is_string($this->password)) { + $iv = Random::string(8); + $symkey = pack('H*', md5($this->password . $iv)); // symkey is short for symmetric key + $symkey.= substr(pack('H*', md5($symkey . $this->password . $iv)), 0, 8); + $des = new TripleDES(); + $des->setKey($symkey); + $des->setIV($iv); + $iv = strtoupper(bin2hex($iv)); + $RSAPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\r\n" . + "Proc-Type: 4,ENCRYPTED\r\n" . + "DEK-Info: DES-EDE3-CBC,$iv\r\n" . + "\r\n" . + chunk_split(base64_encode($des->encrypt($RSAPrivateKey)), 64) . + '-----END RSA PRIVATE KEY-----'; + } else { + $RSAPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\r\n" . + chunk_split(base64_encode($RSAPrivateKey), 64) . + '-----END RSA PRIVATE KEY-----'; + } + + return $RSAPrivateKey; } } /** - * Returns a list of supported formats. + * Convert a public key to the appropriate format + * + * @access private + * @see setPublicKeyFormat() + * @param String $RSAPrivateKey + * @return String + */ + function _convertPublicKey($n, $e) + { + $signed = $this->publicKeyFormat != self::PUBLIC_FORMAT_XML; + + $modulus = $n->toBytes($signed); + $publicExponent = $e->toBytes($signed); + + switch ($this->publicKeyFormat) { + case self::PUBLIC_FORMAT_RAW: + return array('e' => $e->copy(), 'n' => $n->copy()); + case self::PUBLIC_FORMAT_XML: + return "\r\n" . + ' ' . base64_encode($modulus) . "\r\n" . + ' ' . base64_encode($publicExponent) . "\r\n" . + ''; + break; + case self::PUBLIC_FORMAT_OPENSSH: + // from : + // string "ssh-rsa" + // mpint e + // mpint n + $RSAPublicKey = pack('Na*Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($publicExponent), $publicExponent, strlen($modulus), $modulus); + $RSAPublicKey = 'ssh-rsa ' . base64_encode($RSAPublicKey) . ' ' . $this->comment; + + return $RSAPublicKey; + default: // eg. self::PUBLIC_FORMAT_PKCS1_RAW or self::PUBLIC_FORMAT_PKCS1 + // from : + // RSAPublicKey ::= SEQUENCE { + // modulus INTEGER, -- n + // publicExponent INTEGER -- e + // } + $components = array( + 'modulus' => pack('Ca*a*', self::ASN1_INTEGER, $this->_encodeLength(strlen($modulus)), $modulus), + 'publicExponent' => pack('Ca*a*', self::ASN1_INTEGER, $this->_encodeLength(strlen($publicExponent)), $publicExponent) + ); + + $RSAPublicKey = pack( + 'Ca*a*a*', + self::ASN1_SEQUENCE, + $this->_encodeLength(strlen($components['modulus']) + strlen($components['publicExponent'])), + $components['modulus'], + $components['publicExponent'] + ); + + if ($this->publicKeyFormat == self::PUBLIC_FORMAT_PKCS1_RAW) { + $RSAPublicKey = "-----BEGIN RSA PUBLIC KEY-----\r\n" . + chunk_split(base64_encode($RSAPublicKey), 64) . + '-----END RSA PUBLIC KEY-----'; + } else { + // sequence(oid(1.2.840.113549.1.1.1), null)) = rsaEncryption. + $rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA + $RSAPublicKey = chr(0) . $RSAPublicKey; + $RSAPublicKey = chr(3) . $this->_encodeLength(strlen($RSAPublicKey)) . $RSAPublicKey; + + $RSAPublicKey = pack( + 'Ca*a*', + self::ASN1_SEQUENCE, + $this->_encodeLength(strlen($rsaOID . $RSAPublicKey)), + $rsaOID . $RSAPublicKey + ); + + $RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" . + chunk_split(base64_encode($RSAPublicKey), 64) . + '-----END PUBLIC KEY-----'; + } + + return $RSAPublicKey; + } + } + + /** + * Break a public or private key down into its constituant components + * + * @access private + * @see _convertPublicKey() + * @see _convertPrivateKey() + * @param String $key + * @param Integer $type + * @return Array + */ + function _parseKey($key, $type) + { + if ($type != self::PUBLIC_FORMAT_RAW && !is_string($key)) { + return false; + } + + switch ($type) { + case self::PUBLIC_FORMAT_RAW: + if (!is_array($key)) { + return false; + } + $components = array(); + switch (true) { + case isset($key['e']): + $components['publicExponent'] = $key['e']->copy(); + break; + case isset($key['exponent']): + $components['publicExponent'] = $key['exponent']->copy(); + break; + case isset($key['publicExponent']): + $components['publicExponent'] = $key['publicExponent']->copy(); + break; + case isset($key[0]): + $components['publicExponent'] = $key[0]->copy(); + } + switch (true) { + case isset($key['n']): + $components['modulus'] = $key['n']->copy(); + break; + case isset($key['modulo']): + $components['modulus'] = $key['modulo']->copy(); + break; + case isset($key['modulus']): + $components['modulus'] = $key['modulus']->copy(); + break; + case isset($key[1]): + $components['modulus'] = $key[1]->copy(); + } + return isset($components['modulus']) && isset($components['publicExponent']) ? $components : false; + case self::PRIVATE_FORMAT_PKCS1: + case self::PRIVATE_FORMAT_PKCS8: + case self::PUBLIC_FORMAT_PKCS1: + /* Although PKCS#1 proposes a format that public and private keys can use, encrypting them is + "outside the scope" of PKCS#1. PKCS#1 then refers you to PKCS#12 and PKCS#15 if you're wanting to + protect private keys, however, that's not what OpenSSL* does. OpenSSL protects private keys by adding + two new "fields" to the key - DEK-Info and Proc-Type. These fields are discussed here: + + http://tools.ietf.org/html/rfc1421#section-4.6.1.1 + http://tools.ietf.org/html/rfc1421#section-4.6.1.3 + + DES-EDE3-CBC as an algorithm, however, is not discussed anywhere, near as I can tell. + DES-CBC and DES-EDE are discussed in RFC1423, however, DES-EDE3-CBC isn't, nor is its key derivation + function. As is, the definitive authority on this encoding scheme isn't the IETF but rather OpenSSL's + own implementation. ie. the implementation *is* the standard and any bugs that may exist in that + implementation are part of the standard, as well. + + * OpenSSL is the de facto standard. It's utilized by OpenSSH and other projects */ + if (preg_match('#DEK-Info: (.+),(.+)#', $key, $matches)) { + $iv = pack('H*', trim($matches[2])); + $symkey = pack('H*', md5($this->password . substr($iv, 0, 8))); // symkey is short for symmetric key + $symkey.= pack('H*', md5($symkey . $this->password . substr($iv, 0, 8))); + // remove the Proc-Type / DEK-Info sections as they're no longer needed + $key = preg_replace('#^(?:Proc-Type|DEK-Info): .*#m', '', $key); + $ciphertext = $this->_extractBER($key); + if ($ciphertext === false) { + $ciphertext = $key; + } + switch ($matches[1]) { + case 'AES-256-CBC': + $crypto = new AES(); + break; + case 'AES-128-CBC': + $symkey = substr($symkey, 0, 16); + $crypto = new AES(); + break; + case 'DES-EDE3-CFB': + $crypto = new TripleDES(Base::MODE_CFB); + break; + case 'DES-EDE3-CBC': + $symkey = substr($symkey, 0, 24); + $crypto = new TripleDES(); + break; + case 'DES-CBC': + $crypto = new DES(); + break; + default: + return false; + } + $crypto->setKey($symkey); + $crypto->setIV($iv); + $decoded = $crypto->decrypt($ciphertext); + } else { + $decoded = $this->_extractBER($key); + } + + if ($decoded !== false) { + $key = $decoded; + } + + $components = array(); + + if (ord($this->_string_shift($key)) != self::ASN1_SEQUENCE) { + return false; + } + if ($this->_decodeLength($key) != strlen($key)) { + return false; + } + + $tag = ord($this->_string_shift($key)); + /* intended for keys for which OpenSSL's asn1parse returns the following: + + 0:d=0 hl=4 l= 631 cons: SEQUENCE + 4:d=1 hl=2 l= 1 prim: INTEGER :00 + 7:d=1 hl=2 l= 13 cons: SEQUENCE + 9:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption + 20:d=2 hl=2 l= 0 prim: NULL + 22:d=1 hl=4 l= 609 prim: OCTET STRING + + ie. PKCS8 keys*/ + + if ($tag == self::ASN1_INTEGER && substr($key, 0, 3) == "\x01\x00\x30") { + $this->_string_shift($key, 3); + $tag = self::ASN1_SEQUENCE; + } + + if ($tag == self::ASN1_SEQUENCE) { + $temp = $this->_string_shift($key, $this->_decodeLength($key)); + if (ord($this->_string_shift($temp)) != self::ASN1_OBJECT) { + return false; + } + $length = $this->_decodeLength($temp); + switch ($this->_string_shift($temp, $length)) { + case "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01": // rsaEncryption + break; + case "\x2a\x86\x48\x86\xf7\x0d\x01\x05\x03": // pbeWithMD5AndDES-CBC + /* + PBEParameter ::= SEQUENCE { + salt OCTET STRING (SIZE(8)), + iterationCount INTEGER } + */ + if (ord($this->_string_shift($temp)) != self::ASN1_SEQUENCE) { + return false; + } + if ($this->_decodeLength($temp) != strlen($temp)) { + return false; + } + $this->_string_shift($temp); // assume it's an octet string + $salt = $this->_string_shift($temp, $this->_decodeLength($temp)); + if (ord($this->_string_shift($temp)) != self::ASN1_INTEGER) { + return false; + } + $this->_decodeLength($temp); + list(, $iterationCount) = unpack('N', str_pad($temp, 4, chr(0), STR_PAD_LEFT)); + $this->_string_shift($key); // assume it's an octet string + $length = $this->_decodeLength($key); + if (strlen($key) != $length) { + return false; + } + + $crypto = new DES(); + $crypto->setPassword($this->password, 'pbkdf1', 'md5', $salt, $iterationCount); + $key = $crypto->decrypt($key); + if ($key === false) { + return false; + } + return $this->_parseKey($key, self::PRIVATE_FORMAT_PKCS1); + default: + return false; + } + /* intended for keys for which OpenSSL's asn1parse returns the following: + + 0:d=0 hl=4 l= 290 cons: SEQUENCE + 4:d=1 hl=2 l= 13 cons: SEQUENCE + 6:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption + 17:d=2 hl=2 l= 0 prim: NULL + 19:d=1 hl=4 l= 271 prim: BIT STRING */ + $tag = ord($this->_string_shift($key)); // skip over the BIT STRING / OCTET STRING tag + $this->_decodeLength($key); // skip over the BIT STRING / OCTET STRING length + // "The initial octet shall encode, as an unsigned binary integer wtih bit 1 as the least significant bit, the number of + // unused bits in the final subsequent octet. The number shall be in the range zero to seven." + // -- http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf (section 8.6.2.2) + if ($tag == self::ASN1_BITSTRING) { + $this->_string_shift($key); + } + if (ord($this->_string_shift($key)) != self::ASN1_SEQUENCE) { + return false; + } + if ($this->_decodeLength($key) != strlen($key)) { + return false; + } + $tag = ord($this->_string_shift($key)); + } + if ($tag != self::ASN1_INTEGER) { + return false; + } + + $length = $this->_decodeLength($key); + $temp = $this->_string_shift($key, $length); + if (strlen($temp) != 1 || ord($temp) > 2) { + $components['modulus'] = new BigInteger($temp, 256); + $this->_string_shift($key); // skip over self::ASN1_INTEGER + $length = $this->_decodeLength($key); + $components[$type == self::PUBLIC_FORMAT_PKCS1 ? 'publicExponent' : 'privateExponent'] = new BigInteger($this->_string_shift($key, $length), 256); + + return $components; + } + if (ord($this->_string_shift($key)) != self::ASN1_INTEGER) { + return false; + } + $length = $this->_decodeLength($key); + $components['modulus'] = new BigInteger($this->_string_shift($key, $length), 256); + $this->_string_shift($key); + $length = $this->_decodeLength($key); + $components['publicExponent'] = new BigInteger($this->_string_shift($key, $length), 256); + $this->_string_shift($key); + $length = $this->_decodeLength($key); + $components['privateExponent'] = new BigInteger($this->_string_shift($key, $length), 256); + $this->_string_shift($key); + $length = $this->_decodeLength($key); + $components['primes'] = array(1 => new BigInteger($this->_string_shift($key, $length), 256)); + $this->_string_shift($key); + $length = $this->_decodeLength($key); + $components['primes'][] = new BigInteger($this->_string_shift($key, $length), 256); + $this->_string_shift($key); + $length = $this->_decodeLength($key); + $components['exponents'] = array(1 => new BigInteger($this->_string_shift($key, $length), 256)); + $this->_string_shift($key); + $length = $this->_decodeLength($key); + $components['exponents'][] = new BigInteger($this->_string_shift($key, $length), 256); + $this->_string_shift($key); + $length = $this->_decodeLength($key); + $components['coefficients'] = array(2 => new BigInteger($this->_string_shift($key, $length), 256)); + + if (!empty($key)) { + if (ord($this->_string_shift($key)) != self::ASN1_SEQUENCE) { + return false; + } + $this->_decodeLength($key); + while (!empty($key)) { + if (ord($this->_string_shift($key)) != self::ASN1_SEQUENCE) { + return false; + } + $this->_decodeLength($key); + $key = substr($key, 1); + $length = $this->_decodeLength($key); + $components['primes'][] = new BigInteger($this->_string_shift($key, $length), 256); + $this->_string_shift($key); + $length = $this->_decodeLength($key); + $components['exponents'][] = new BigInteger($this->_string_shift($key, $length), 256); + $this->_string_shift($key); + $length = $this->_decodeLength($key); + $components['coefficients'][] = new BigInteger($this->_string_shift($key, $length), 256); + } + } + + return $components; + case self::PUBLIC_FORMAT_OPENSSH: + $parts = explode(' ', $key, 3); + + $key = isset($parts[1]) ? base64_decode($parts[1]) : false; + if ($key === false) { + return false; + } + + $comment = isset($parts[2]) ? $parts[2] : false; + + $cleanup = substr($key, 0, 11) == "\0\0\0\7ssh-rsa"; + + if (strlen($key) <= 4) { + return false; + } + extract(unpack('Nlength', $this->_string_shift($key, 4))); + $publicExponent = new BigInteger($this->_string_shift($key, $length), -256); + if (strlen($key) <= 4) { + return false; + } + extract(unpack('Nlength', $this->_string_shift($key, 4))); + $modulus = new BigInteger($this->_string_shift($key, $length), -256); + + if ($cleanup && strlen($key)) { + if (strlen($key) <= 4) { + return false; + } + extract(unpack('Nlength', $this->_string_shift($key, 4))); + $realModulus = new BigInteger($this->_string_shift($key, $length), -256); + return strlen($key) ? false : array( + 'modulus' => $realModulus, + 'publicExponent' => $modulus, + 'comment' => $comment + ); + } else { + return strlen($key) ? false : array( + 'modulus' => $modulus, + 'publicExponent' => $publicExponent, + 'comment' => $comment + ); + } + // http://www.w3.org/TR/xmldsig-core/#sec-RSAKeyValue + // http://en.wikipedia.org/wiki/XML_Signature + case self::PRIVATE_FORMAT_XML: + case self::PUBLIC_FORMAT_XML: + $this->components = array(); + + $xml = xml_parser_create('UTF-8'); + xml_set_object($xml, $this); + xml_set_element_handler($xml, '_start_element_handler', '_stop_element_handler'); + xml_set_character_data_handler($xml, '_data_handler'); + // add to account for "dangling" tags like ... that are sometimes added + if (!xml_parse($xml, '' . $key . '')) { + return false; + } + + return isset($this->components['modulus']) && isset($this->components['publicExponent']) ? $this->components : false; + // from PuTTY's SSHPUBK.C + case self::PRIVATE_FORMAT_PUTTY: + $components = array(); + $key = preg_split('#\r\n|\r|\n#', $key); + $type = trim(preg_replace('#PuTTY-User-Key-File-2: (.+)#', '$1', $key[0])); + if ($type != 'ssh-rsa') { + return false; + } + $encryption = trim(preg_replace('#Encryption: (.+)#', '$1', $key[1])); + $comment = trim(preg_replace('#Comment: (.+)#', '$1', $key[2])); + + $publicLength = trim(preg_replace('#Public-Lines: (\d+)#', '$1', $key[3])); + $public = base64_decode(implode('', array_map('trim', array_slice($key, 4, $publicLength)))); + $public = substr($public, 11); + extract(unpack('Nlength', $this->_string_shift($public, 4))); + $components['publicExponent'] = new BigInteger($this->_string_shift($public, $length), -256); + extract(unpack('Nlength', $this->_string_shift($public, 4))); + $components['modulus'] = new BigInteger($this->_string_shift($public, $length), -256); + + $privateLength = trim(preg_replace('#Private-Lines: (\d+)#', '$1', $key[$publicLength + 4])); + $private = base64_decode(implode('', array_map('trim', array_slice($key, $publicLength + 5, $privateLength)))); + + switch ($encryption) { + case 'aes256-cbc': + $symkey = ''; + $sequence = 0; + while (strlen($symkey) < 32) { + $temp = pack('Na*', $sequence++, $this->password); + $symkey.= pack('H*', sha1($temp)); + } + $symkey = substr($symkey, 0, 32); + $crypto = new AES(); + } + + if ($encryption != 'none') { + $crypto->setKey($symkey); + $crypto->disablePadding(); + $private = $crypto->decrypt($private); + if ($private === false) { + return false; + } + } + + extract(unpack('Nlength', $this->_string_shift($private, 4))); + if (strlen($private) < $length) { + return false; + } + $components['privateExponent'] = new BigInteger($this->_string_shift($private, $length), -256); + extract(unpack('Nlength', $this->_string_shift($private, 4))); + if (strlen($private) < $length) { + return false; + } + $components['primes'] = array(1 => new BigInteger($this->_string_shift($private, $length), -256)); + extract(unpack('Nlength', $this->_string_shift($private, 4))); + if (strlen($private) < $length) { + return false; + } + $components['primes'][] = new BigInteger($this->_string_shift($private, $length), -256); + + $temp = $components['primes'][1]->subtract($this->one); + $components['exponents'] = array(1 => $components['publicExponent']->modInverse($temp)); + $temp = $components['primes'][2]->subtract($this->one); + $components['exponents'][] = $components['publicExponent']->modInverse($temp); + + extract(unpack('Nlength', $this->_string_shift($private, 4))); + if (strlen($private) < $length) { + return false; + } + $components['coefficients'] = array(2 => new BigInteger($this->_string_shift($private, $length), -256)); + + return $components; + } + } + + /** + * Returns the key size + * + * More specifically, this returns the size of the modulo in bits. * * @access public - * @return array + * @return Integer */ - static function getSupportedFormats() + function getSize() { - self::_initialize_static_variables(); + return !isset($this->modulus) ? 0 : strlen($this->modulus->toBits()); + } - return self::$origFileFormats; + /** + * Start Element Handler + * + * Called by xml_set_element_handler() + * + * @access private + * @param Resource $parser + * @param String $name + * @param Array $attribs + */ + function _start_element_handler($parser, $name, $attribs) + { + //$name = strtoupper($name); + switch ($name) { + case 'MODULUS': + $this->current = &$this->components['modulus']; + break; + case 'EXPONENT': + $this->current = &$this->components['publicExponent']; + break; + case 'P': + $this->current = &$this->components['primes'][1]; + break; + case 'Q': + $this->current = &$this->components['primes'][2]; + break; + case 'DP': + $this->current = &$this->components['exponents'][1]; + break; + case 'DQ': + $this->current = &$this->components['exponents'][2]; + break; + case 'INVERSEQ': + $this->current = &$this->components['coefficients'][2]; + break; + case 'D': + $this->current = &$this->components['privateExponent']; + } + $this->current = ''; + } + + /** + * Stop Element Handler + * + * Called by xml_set_element_handler() + * + * @access private + * @param Resource $parser + * @param String $name + */ + function _stop_element_handler($parser, $name) + { + if (isset($this->current)) { + $this->current = new BigInteger(base64_decode($this->current), 256); + unset($this->current); + } + } + + /** + * Data Handler + * + * Called by xml_set_character_data_handler() + * + * @access private + * @param Resource $parser + * @param String $data + */ + function _data_handler($parser, $data) + { + if (!isset($this->current) || is_object($this->current)) { + return; + } + $this->current.= trim($data); } /** @@ -679,10 +1511,10 @@ class RSA * Returns true on success and false on failure (ie. an incorrect password was provided or the key was malformed) * * @access public - * @param string $key - * @param int $type optional + * @param String $key + * @param Integer $type optional */ - function load($key, $type = false) + function loadKey($key, $type = false) { if ($key instanceof RSA) { $this->privateKeyFormat = $key->privateKeyFormat; @@ -691,7 +1523,11 @@ class RSA $this->hLen = $key->hLen; $this->sLen = $key->sLen; $this->mgfHLen = $key->mgfHLen; + $this->encryptionMode = $key->encryptionMode; + $this->signatureMode = $key->signatureMode; $this->password = $key->password; + $this->configFile = $key->configFile; + $this->comment = $key->comment; if (is_object($key->hash)) { $this->hash = new Hash($key->hash->getHash()); @@ -701,13 +1537,13 @@ class RSA } if (is_object($key->modulus)) { - $this->modulus = clone $key->modulus; + $this->modulus = $key->modulus->copy(); } if (is_object($key->exponent)) { - $this->exponent = clone $key->exponent; + $this->exponent = $key->exponent->copy(); } if (is_object($key->publicExponent)) { - $this->publicExponent = clone $key->publicExponent; + $this->publicExponent = $key->publicExponent->copy(); } $this->primes = array(); @@ -715,49 +1551,44 @@ class RSA $this->coefficients = array(); foreach ($this->primes as $prime) { - $this->primes[] = clone $prime; + $this->primes[] = $prime->copy(); } foreach ($this->exponents as $exponent) { - $this->exponents[] = clone $exponent; + $this->exponents[] = $exponent->copy(); } foreach ($this->coefficients as $coefficient) { - $this->coefficients[] = clone $coefficient; + $this->coefficients[] = $coefficient->copy(); } return true; } - $components = false; if ($type === false) { - foreach (self::$fileFormats as $format) { - try { - $components = $format::load($key, $this->password); - } catch (\Exception $e) { - $components = false; - } + $types = array( + self::PUBLIC_FORMAT_RAW, + self::PRIVATE_FORMAT_PKCS1, + self::PRIVATE_FORMAT_XML, + self::PRIVATE_FORMAT_PUTTY, + self::PUBLIC_FORMAT_OPENSSH + ); + foreach ($types as $type) { + $components = $this->_parseKey($key, $type); if ($components !== false) { break; } } + } else { - $format = strtolower($type); - if (isset(self::$fileFormats[$format])) { - $format = self::$fileFormats[$format]; - try { - $components = $format::load($key, $this->password); - } catch (\Exception $e) { - $components = false; - } - } + $components = $this->_parseKey($key, $type); } if ($components === false) { - $this->format = false; return false; } - $this->format = $format; - + if (isset($components['comment']) && $components['comment'] !== false) { + $this->comment = $components['comment']; + } $this->modulus = $components['modulus']; $this->k = strlen($this->modulus->toBytes()); $this->exponent = isset($components['privateExponent']) ? $components['privateExponent'] : $components['publicExponent']; @@ -773,88 +1604,32 @@ class RSA $this->publicExponent = false; } - if ($components['isPublicKey']) { - $this->setPublicKey(); + switch ($type) { + case self::PUBLIC_FORMAT_OPENSSH: + case self::PUBLIC_FORMAT_RAW: + $this->setPublicKey(); + break; + case self::PRIVATE_FORMAT_PKCS1: + switch (true) { + case strpos($key, '-BEGIN PUBLIC KEY-') !== false: + case strpos($key, '-BEGIN RSA PUBLIC KEY-') !== false: + $this->setPublicKey(); + } } return true; } - /** - * Returns the format of the loaded key. - * - * If the key that was loaded wasn't in a valid or if the key was auto-generated - * with RSA::createKey() then this will return false. - * - * @see self::load() - * @access public - * @return mixed - */ - function getLoadedFormat() - { - if ($this->format === false) { - return false; - } - - $meta = new \ReflectionClass($this->format); - return $meta->getShortName(); - } - - /** - * Returns the private key - * - * The private key is only returned if the currently loaded key contains the constituent prime numbers. - * - * @see self::getPublicKey() - * @access public - * @param string $type optional - * @return mixed - */ - function getPrivateKey($type = 'PKCS1') - { - $type = strtolower($type); - if (!isset(self::$fileFormats[$type])) { - return false; - } - $type = self::$fileFormats[$type]; - if (!method_exists($type, 'savePrivateKey')) { - return false; - } - - if (empty($this->primes)) { - return false; - } - - $oldFormat = $this->privateKeyFormat; - $this->privateKeyFormat = $type; - $temp = $type::savePrivateKey($this->modulus, $this->publicExponent, $this->exponent, $this->primes, $this->exponents, $this->coefficients, $this->password); - $this->privateKeyFormat = $oldFormat; - return $temp; - } - - /** - * Returns the key size - * - * More specifically, this returns the size of the modulo in bits. - * - * @access public - * @return int - */ - function getSize() - { - return !isset($this->modulus) ? 0 : strlen($this->modulus->toBits()); - } - /** * Sets the password * * Private keys can be encrypted with a password. To unset the password, pass in the empty string or false. * Or rather, pass in $password such that empty($password) && !is_string($password) is true. * - * @see self::createKey() - * @see self::load() + * @see createKey() + * @see loadKey() * @access public - * @param string $password + * @param String $password */ function setPassword($password = false) { @@ -876,11 +1651,11 @@ class RSA * * Returns true on success, false on failure * - * @see self::getPublicKey() + * @see getPublicKey() * @access public - * @param string $key optional - * @param int $type optional - * @return bool + * @param String $key optional + * @param Integer $type optional + * @return Boolean */ function setPublicKey($key = false, $type = false) { @@ -894,40 +1669,27 @@ class RSA return true; } - $components = false; if ($type === false) { - foreach (self::$fileFormats as $format) { - if (!method_exists($format, 'savePublicKey')) { - continue; - } - try { - $components = $format::load($key, $this->password); - } catch (\Exception $e) { - $components = false; - } + $types = array( + self::PUBLIC_FORMAT_RAW, + self::PUBLIC_FORMAT_PKCS1, + self::PUBLIC_FORMAT_XML, + self::PUBLIC_FORMAT_OPENSSH + ); + foreach ($types as $type) { + $components = $this->_parseKey($key, $type); if ($components !== false) { break; } } } else { - $format = strtolower($type); - if (isset(self::$fileFormats[$format])) { - $format = self::$fileFormats[$format]; - try { - $components = $format::load($key, $this->password); - } catch (\Exception $e) { - $components = false; - } - } + $components = $this->_parseKey($key, $type); } if ($components === false) { - $this->format = false; return false; } - $this->format = $format; - if (empty($this->modulus) || !$this->modulus->equals($components['modulus'])) { $this->modulus = $components['modulus']; $this->exponent = $this->publicExponent = $components['publicExponent']; @@ -949,27 +1711,27 @@ class RSA * * Returns true on success, false on failure * - * @see self::getPublicKey() + * @see getPublicKey() * @access public - * @param string $key optional - * @param int $type optional - * @return bool + * @param String $key optional + * @param Integer $type optional + * @return Boolean */ function setPrivateKey($key = false, $type = false) { if ($key === false && !empty($this->publicExponent)) { - $this->publicExponent = false; + unset($this->publicExponent); return true; } $rsa = new RSA(); - if (!$rsa->load($key, $type)) { + if (!$rsa->loadKey($key, $type)) { return false; } - $rsa->publicExponent = false; + unset($rsa->publicExponent); // don't overwrite the old key if the new key is invalid - $this->load($rsa); + $this->loadKey($rsa); return true; } @@ -980,29 +1742,20 @@ class RSA * or if the public key was set via setPublicKey(). If the currently loaded key is supposed to be the public key this * function won't return it since this library, for the most part, doesn't distinguish between public and private keys. * - * @see self::getPrivateKey() + * @see getPublicKey() * @access public - * @param string $type optional - * @return mixed + * @param String $key + * @param Integer $type optional */ - function getPublicKey($type = 'PKCS8') + function getPublicKey($type = self::PUBLIC_FORMAT_PKCS8) { - $type = strtolower($type); - if (!isset(self::$fileFormats[$type])) { - return false; - } - $type = self::$fileFormats[$type]; - if (!method_exists($type, 'savePublicKey')) { - return false; - } - if (empty($this->modulus) || empty($this->publicExponent)) { return false; } $oldFormat = $this->publicKeyFormat; $this->publicKeyFormat = $type; - $temp = $type::savePublicKey($this->modulus, $this->publicExponent); + $temp = $this->_convertPublicKey($this->modulus, $this->publicExponent); $this->publicKeyFormat = $oldFormat; return $temp; } @@ -1015,9 +1768,8 @@ class RSA * Example output (md5): "c1:b1:30:29:d7:b8:de:6c:97:77:10:d7:46:41:63:87" (as specified by RFC 4716) * * @access public - * @param string $algorithm The hashing algorithm to be used. Valid options are 'md5' and 'sha256'. False is returned + * @param String $algorithm The hashing algorithm to be used. Valid options are 'md5' and 'sha256'. False is returned * for invalid values. - * @return mixed */ public function getPublicKeyFingerprint($algorithm = 'md5') { @@ -1040,6 +1792,30 @@ class RSA default: return false; } + + } + + /** + * Returns the private key + * + * The private key is only returned if the currently loaded key contains the constituent prime numbers. + * + * @see getPublicKey() + * @access public + * @param String $key + * @param Integer $type optional + */ + function getPrivateKey($type = self::PUBLIC_FORMAT_PKCS1) + { + if (empty($this->primes)) { + return false; + } + + $oldFormat = $this->privateKeyFormat; + $this->privateKeyFormat = $type; + $temp = $this->_convertPrivateKey($this->modulus, $this->publicExponent, $this->exponent, $this->primes, $this->exponents, $this->coefficients); + $this->privateKeyFormat = $oldFormat; + return $temp; } /** @@ -1048,60 +1824,48 @@ class RSA * Returns the private key without the prime number constituants. Structurally identical to a public key that * hasn't been set as the public key * - * @see self::getPrivateKey() + * @see getPrivateKey() * @access private - * @param string $type optional - * @return mixed + * @param String $key + * @param Integer $type optional */ - function _getPrivatePublicKey($type = 'PKCS8') + function _getPrivatePublicKey($mode = self::PUBLIC_FORMAT_PKCS8) { - $type = strtolower($type); - if (!isset(self::$fileFormats[$type])) { - return false; - } - $type = self::$fileFormats[$type]; - if (!method_exists($type, 'savePublicKey')) { - return false; - } - if (empty($this->modulus) || empty($this->exponent)) { return false; } $oldFormat = $this->publicKeyFormat; - $this->publicKeyFormat = $type; - $temp = $type::savePublicKey($this->modulus, $this->exponent); + $this->publicKeyFormat = $mode; + $temp = $this->_convertPublicKey($this->modulus, $this->exponent); $this->publicKeyFormat = $oldFormat; return $temp; } - /** - * __toString() magic method + * __toString() magic method * * @access public - * @return string */ function __toString() { $key = $this->getPrivateKey($this->privateKeyFormat); - if (is_string($key)) { + if ($key !== false) { return $key; } $key = $this->_getPrivatePublicKey($this->publicKeyFormat); - return is_string($key) ? $key : ''; + return $key !== false ? $key : ''; } /** - * __clone() magic method + * __clone() magic method * * @access public - * @return \phpseclib\Crypt\RSA */ function __clone() { $key = new RSA(); - $key->load($this); + $key->loadKey($this); return $key; } @@ -1109,10 +1873,10 @@ class RSA * Generates the smallest and largest numbers requiring $bits bits * * @access private - * @param int $bits - * @return array + * @param Integer $bits + * @return Array */ - static function _generateMinMax($bits) + function _generateMinMax($bits) { $bytes = $bits >> 3; $min = str_repeat(chr(0), $bytes); @@ -1138,8 +1902,8 @@ class RSA * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information. * * @access private - * @param string $string - * @return int + * @param String $string + * @return Integer */ function _decodeLength(&$string) { @@ -1159,8 +1923,8 @@ class RSA * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information. * * @access private - * @param int $length - * @return string + * @param Integer $length + * @return String */ function _encodeLength($length) { @@ -1177,9 +1941,9 @@ class RSA * * Inspired by array_shift * - * @param string $string - * @param int $index - * @return string + * @param String $string + * @param optional Integer $index + * @return String * @access private */ function _string_shift(&$string, $index = 1) @@ -1192,9 +1956,9 @@ class RSA /** * Determines the private key format * - * @see self::createKey() + * @see createKey() * @access public - * @param int $format + * @param Integer $format */ function setPrivateKeyFormat($format) { @@ -1204,9 +1968,9 @@ class RSA /** * Determines the public key format * - * @see self::createKey() + * @see createKey() * @access public - * @param int $format + * @param Integer $format */ function setPublicKeyFormat($format) { @@ -1216,11 +1980,11 @@ class RSA /** * Determines which hashing function should be used * - * Used with signature production / verification and (if the encryption mode is self::PADDING_OAEP) encryption and - * decryption. If $hash isn't supported, sha256 is used. + * Used with signature production / verification and (if the encryption mode is self::ENCRYPTION_OAEP) encryption and + * decryption. If $hash isn't supported, sha1 is used. * * @access public - * @param string $hash + * @param String $hash */ function setHash($hash) { @@ -1232,15 +1996,12 @@ class RSA case 'sha256': case 'sha384': case 'sha512': - case 'sha224': - case 'sha512/224': - case 'sha512/256': $this->hash = new Hash($hash); $this->hashName = $hash; break; default: - $this->hash = new Hash('sha256'); - $this->hashName = 'sha256'; + $this->hash = new Hash('sha1'); + $this->hashName = 'sha1'; } $this->hLen = $this->hash->getLength(); } @@ -1248,11 +2009,11 @@ class RSA /** * Determines which hashing function should be used for the mask generation function * - * The mask generation function is used by self::PADDING_OAEP and self::PADDING_PSS and although it's + * The mask generation function is used by self::ENCRYPTION_OAEP and self::SIGNATURE_PSS and although it's * best if Hash and MGFHash are set to the same thing this is not a requirement. * * @access public - * @param string $hash + * @param String $hash */ function setMGFHash($hash) { @@ -1264,13 +2025,10 @@ class RSA case 'sha256': case 'sha384': case 'sha512': - case 'sha224': - case 'sha512/224': - case 'sha512/256': $this->mgfHash = new Hash($hash); break; default: - $this->mgfHash = new Hash('sha256'); + $this->mgfHash = new Hash('sha1'); } $this->mgfHLen = $this->mgfHash->getLength(); } @@ -1284,7 +2042,7 @@ class RSA * of the hash function Hash) and 0. * * @access public - * @param int $format + * @param Integer $format */ function setSaltLength($sLen) { @@ -1297,17 +2055,15 @@ class RSA * See {@link http://tools.ietf.org/html/rfc3447#section-4.1 RFC3447#section-4.1}. * * @access private - * @param bool|\phpseclib\Math\BigInteger $x - * @param int $xLen - * @return bool|string + * @param \phpseclib\Math\BigInteger $x + * @param Integer $xLen + * @return String */ function _i2osp($x, $xLen) { - if ($x === false) { - return false; - } $x = $x->toBytes(); if (strlen($x) > $xLen) { + user_error('Integer too large'); return false; } return str_pad($x, $xLen, chr(0), STR_PAD_LEFT); @@ -1319,7 +2075,7 @@ class RSA * See {@link http://tools.ietf.org/html/rfc3447#section-4.2 RFC3447#section-4.2}. * * @access private - * @param string $x + * @param String $x * @return \phpseclib\Math\BigInteger */ function _os2ip($x) @@ -1374,7 +2130,9 @@ class RSA } } - $r = BigInteger::random(self::$one, $smallest->subtract(self::$one)); + $one = new BigInteger(1); + + $r = $one->random($one, $smallest->subtract($one)); $m_i = array( 1 => $this->_blind($x, $r, 1), @@ -1411,7 +2169,7 @@ class RSA * @access private * @param \phpseclib\Math\BigInteger $x * @param \phpseclib\Math\BigInteger $r - * @param int $i + * @param Integer $i * @return \phpseclib\Math\BigInteger */ function _blind($x, $r, $i) @@ -1436,9 +2194,9 @@ class RSA * Thanks for the heads up singpolyma! * * @access private - * @param string $x - * @param string $y - * @return bool + * @param String $x + * @param String $y + * @return Boolean */ function _equals($x, $y) { @@ -1461,11 +2219,12 @@ class RSA * * @access private * @param \phpseclib\Math\BigInteger $m - * @return bool|\phpseclib\Math\BigInteger + * @return \phpseclib\Math\BigInteger */ function _rsaep($m) { - if ($m->compare(self::$zero) < 0 || $m->compare($this->modulus) > 0) { + if ($m->compare($this->zero) < 0 || $m->compare($this->modulus) > 0) { + user_error('Message representative out of range'); return false; } return $this->_exponentiate($m); @@ -1478,11 +2237,12 @@ class RSA * * @access private * @param \phpseclib\Math\BigInteger $c - * @return bool|\phpseclib\Math\BigInteger + * @return \phpseclib\Math\BigInteger */ function _rsadp($c) { - if ($c->compare(self::$zero) < 0 || $c->compare($this->modulus) > 0) { + if ($c->compare($this->zero) < 0 || $c->compare($this->modulus) > 0) { + user_error('Ciphertext representative out of range'); return false; } return $this->_exponentiate($c); @@ -1495,11 +2255,12 @@ class RSA * * @access private * @param \phpseclib\Math\BigInteger $m - * @return bool|\phpseclib\Math\BigInteger + * @return \phpseclib\Math\BigInteger */ function _rsasp1($m) { - if ($m->compare(self::$zero) < 0 || $m->compare($this->modulus) > 0) { + if ($m->compare($this->zero) < 0 || $m->compare($this->modulus) > 0) { + user_error('Message representative out of range'); return false; } return $this->_exponentiate($m); @@ -1512,11 +2273,12 @@ class RSA * * @access private * @param \phpseclib\Math\BigInteger $s - * @return bool|\phpseclib\Math\BigInteger + * @return \phpseclib\Math\BigInteger */ function _rsavp1($s) { - if ($s->compare(self::$zero) < 0 || $s->compare($this->modulus) > 0) { + if ($s->compare($this->zero) < 0 || $s->compare($this->modulus) > 0) { + user_error('Signature representative out of range'); return false; } return $this->_exponentiate($s); @@ -1528,9 +2290,9 @@ class RSA * See {@link http://tools.ietf.org/html/rfc3447#appendix-B.2.1 RFC3447#appendix-B.2.1}. * * @access private - * @param string $mgfSeed - * @param int $mgfLen - * @return string + * @param String $mgfSeed + * @param Integer $mgfLen + * @return String */ function _mgf1($mgfSeed, $maskLen) { @@ -1553,10 +2315,9 @@ class RSA * {http://en.wikipedia.org/wiki/Optimal_Asymmetric_Encryption_Padding OAES}. * * @access private - * @param string $m - * @param string $l - * @throws \OutOfBoundsException if strlen($m) > $this->k - 2 * $this->hLen - 2 - * @return string + * @param String $m + * @param String $l + * @return String */ function _rsaes_oaep_encrypt($m, $l = '') { @@ -1568,7 +2329,8 @@ class RSA // be output. if ($mLen > $this->k - 2 * $this->hLen - 2) { - throw new \OutOfBoundsException('Message too long'); + user_error('Message too long'); + return false; } // EME-OAEP encoding @@ -1616,9 +2378,9 @@ class RSA * this document. * * @access private - * @param string $c - * @param string $l - * @return bool|string + * @param String $c + * @param String $l + * @return String */ function _rsaes_oaep_decrypt($c, $l = '') { @@ -1628,6 +2390,7 @@ class RSA // be output. if (strlen($c) != $this->k || $this->k < 2 * $this->hLen + 2) { + user_error('Decryption error'); return false; } @@ -1635,10 +2398,11 @@ class RSA $c = $this->_os2ip($c); $m = $this->_rsadp($c); - $em = $this->_i2osp($m, $this->k); - if ($em === false) { + if ($m === false) { + user_error('Decryption error'); return false; } + $em = $this->_i2osp($m, $this->k); // EME-OAEP decoding @@ -1653,10 +2417,12 @@ class RSA $lHash2 = substr($db, 0, $this->hLen); $m = substr($db, $this->hLen); if ($lHash != $lHash2) { + user_error('Decryption error'); return false; } $m = ltrim($m, chr(0)); if (ord($m[0]) != 1) { + user_error('Decryption error'); return false; } @@ -1671,16 +2437,11 @@ class RSA * Doesn't use padding and is not recommended. * * @access private - * @param string $m - * @return bool|string - * @throws \OutOfBoundsException if strlen($m) > $this->k + * @param String $m + * @return String */ function _raw_encrypt($m) { - if (strlen($m) > $this->k) { - throw new \OutOfBoundsException('Message too long'); - } - $temp = $this->_os2ip($m); $temp = $this->_rsaep($temp); return $this->_i2osp($temp, $this->k); @@ -1692,19 +2453,18 @@ class RSA * See {@link http://tools.ietf.org/html/rfc3447#section-7.2.1 RFC3447#section-7.2.1}. * * @access private - * @param string $m - * @param bool $pkcs15_compat optional - * @throws \OutOfBoundsException if strlen($m) > $this->k - 11 - * @return bool|string + * @param String $m + * @return String */ - function _rsaes_pkcs1_v1_5_encrypt($m, $pkcs15_compat = false) + function _rsaes_pkcs1_v1_5_encrypt($m) { $mLen = strlen($m); // Length checking if ($mLen > $this->k - 11) { - throw new \OutOfBoundsException('Message too long'); + user_error('Message too long'); + return false; } // EME-PKCS1-v1_5 encoding @@ -1718,7 +2478,7 @@ class RSA } $type = 2; // see the comments of _rsaes_pkcs1_v1_5_decrypt() to understand why this is being done - if ($pkcs15_compat && (!isset($this->publicExponent) || $this->exponent !== $this->publicExponent)) { + if (defined('CRYPT_RSA_PKCS15_COMPAT') && (!isset($this->publicExponent) || $this->exponent !== $this->publicExponent)) { $type = 1; // "The padding string PS shall consist of k-3-||D|| octets. ... for block type 01, they shall have value FF" $ps = str_repeat("\xFF", $psLen); @@ -1752,14 +2512,15 @@ class RSA * not private key encrypted ciphertext's. * * @access private - * @param string $c - * @return bool|string + * @param String $c + * @return String */ function _rsaes_pkcs1_v1_5_decrypt($c) { // Length checking if (strlen($c) != $this->k) { // or if k < 11 + user_error('Decryption error'); return false; } @@ -1767,14 +2528,17 @@ class RSA $c = $this->_os2ip($c); $m = $this->_rsadp($c); - $em = $this->_i2osp($m, $this->k); - if ($em === false) { + + if ($m === false) { + user_error('Decryption error'); return false; } + $em = $this->_i2osp($m, $this->k); // EME-PKCS1-v1_5 decoding if (ord($em[0]) != 0 || ord($em[1]) > 2) { + user_error('Decryption error'); return false; } @@ -1782,6 +2546,7 @@ class RSA $m = substr($em, strlen($ps) + 3); if (strlen($ps) < 8) { + user_error('Decryption error'); return false; } @@ -1796,9 +2561,8 @@ class RSA * See {@link http://tools.ietf.org/html/rfc3447#section-9.1.1 RFC3447#section-9.1.1}. * * @access private - * @param string $m - * @throws \RuntimeException on encoding error - * @param int $emBits + * @param String $m + * @param Integer $emBits */ function _emsa_pss_encode($m, $emBits) { @@ -1806,10 +2570,11 @@ class RSA // be output. $emLen = ($emBits + 1) >> 3; // ie. ceil($emBits / 8) - $sLen = $this->sLen ? $this->sLen : $this->hLen; + $sLen = $this->sLen === false ? $this->hLen : $this->sLen; $mHash = $this->hash->hash($m); if ($emLen < $this->hLen + $sLen + 2) { + user_error('Encoding error'); return false; } @@ -1832,10 +2597,10 @@ class RSA * See {@link http://tools.ietf.org/html/rfc3447#section-9.1.2 RFC3447#section-9.1.2}. * * @access private - * @param string $m - * @param string $em - * @param int $emBits - * @return string + * @param String $m + * @param String $em + * @param Integer $emBits + * @return String */ function _emsa_pss_verify($m, $em, $emBits) { @@ -1843,7 +2608,7 @@ class RSA // be output. $emLen = ($emBits + 1) >> 3; // ie. ceil($emBits / 8); - $sLen = $this->sLen ? $this->sLen : $this->hLen; + $sLen = $this->sLen === false ? $this->hLen : $this->sLen; $mHash = $this->hash->hash($m); if ($emLen < $this->hLen + $sLen + 2) { @@ -1879,8 +2644,8 @@ class RSA * See {@link http://tools.ietf.org/html/rfc3447#section-8.1.1 RFC3447#section-8.1.1}. * * @access private - * @param string $m - * @return bool|string + * @param String $m + * @return String */ function _rsassa_pss_sign($m) { @@ -1905,15 +2670,16 @@ class RSA * See {@link http://tools.ietf.org/html/rfc3447#section-8.1.2 RFC3447#section-8.1.2}. * * @access private - * @param string $m - * @param string $s - * @return bool|string + * @param String $m + * @param String $s + * @return String */ function _rsassa_pss_verify($m, $s) { // Length checking if (strlen($s) != $this->k) { + user_error('Invalid signature'); return false; } @@ -1923,8 +2689,13 @@ class RSA $s2 = $this->_os2ip($s); $m2 = $this->_rsavp1($s2); + if ($m2 === false) { + user_error('Invalid signature'); + return false; + } $em = $this->_i2osp($m2, $modBits >> 3); if ($em === false) { + user_error('Invalid signature'); return false; } @@ -1939,14 +2710,16 @@ class RSA * See {@link http://tools.ietf.org/html/rfc3447#section-9.2 RFC3447#section-9.2}. * * @access private - * @param string $m - * @param int $emLen - * @throws \LengthException if the intended encoded message length is too short - * @return string + * @param String $m + * @param Integer $emLen + * @return String */ function _emsa_pkcs1_v1_5_encode($m, $emLen) { $h = $this->hash->hash($m); + if ($h === false) { + return false; + } // see http://tools.ietf.org/html/rfc3447#page-43 switch ($this->hashName) { @@ -1967,22 +2740,13 @@ class RSA break; case 'sha512': $t = pack('H*', '3051300d060960864801650304020305000440'); - break; - // from https://www.emc.com/collateral/white-papers/h11300-pkcs-1v2-2-rsa-cryptography-standard-wp.pdf#page=40 - case 'sha224': - $t = pack('H*', '302d300d06096086480165030402040500041c'); - break; - case 'sha512/224': - $t = pack('H*', '302d300d06096086480165030402050500041c'); - break; - case 'sha512/256': - $t = pack('H*', '3031300d060960864801650304020605000420'); } $t.= $h; $tLen = strlen($t); if ($emLen < $tLen + 11) { - throw new \LengthException('Intended encoded message length too short'); + user_error('Intended encoded message length too short'); + return false; } $ps = str_repeat(chr(0xFF), $emLen - $tLen - 3); @@ -1998,20 +2762,17 @@ class RSA * See {@link http://tools.ietf.org/html/rfc3447#section-8.2.1 RFC3447#section-8.2.1}. * * @access private - * @param string $m - * @throws \LengthException if the RSA modulus is too short - * @return bool|string + * @param String $m + * @return String */ function _rsassa_pkcs1_v1_5_sign($m) { // EMSA-PKCS1-v1_5 encoding - // If the encoding operation outputs "intended encoded message length too short," output "RSA modulus - // too short" and stop. - try { - $em = $this->_emsa_pkcs1_v1_5_encode($m, $this->k); - } catch (\LengthException $e) { - throw new \LengthException('RSA modulus too short'); + $em = $this->_emsa_pkcs1_v1_5_encode($m, $this->k); + if ($em === false) { + user_error('RSA modulus too short'); + return false; } // RSA signature @@ -2031,65 +2792,15 @@ class RSA * See {@link http://tools.ietf.org/html/rfc3447#section-8.2.2 RFC3447#section-8.2.2}. * * @access private - * @param string $m - * @param string $s - * @throws \LengthException if the RSA modulus is too short - * @return bool + * @param String $m + * @return String */ function _rsassa_pkcs1_v1_5_verify($m, $s) { // Length checking if (strlen($s) != $this->k) { - return false; - } - - // RSA verification - - $s = $this->_os2ip($s); - $m2 = $this->_rsavp1($s); - $em = $this->_i2osp($m2, $this->k); - if ($em === false) { - return false; - } - - // EMSA-PKCS1-v1_5 encoding - - // If the encoding operation outputs "intended encoded message length too short," output "RSA modulus - // too short" and stop. - try { - $em2 = $this->_emsa_pkcs1_v1_5_encode($m, $this->k); - } catch (\LengthException $e) { - throw new \LengthException('RSA modulus too short'); - } - - // Compare - return $this->_equals($em, $em2); - } - - /** - * RSASSA-PKCS1-V1_5-VERIFY (relaxed matching) - * - * Per {@link http://tools.ietf.org/html/rfc3447#page-43 RFC3447#page-43} PKCS1 v1.5 - * specified the use BER encoding rather than DER encoding that PKCS1 v2.0 specified. - * This means that under rare conditions you can have a perfectly valid v1.5 signature - * that fails to validate with _rsassa_pkcs1_v1_5_verify(). PKCS1 v2.1 also recommends - * that if you're going to validate these types of signatures you "should indicate - * whether the underlying BER encoding is a DER encoding and hence whether the signature - * is valid with respect to the specification given in [PKCS1 v2.0+]". so if you do - * $rsa->getLastPadding() and get RSA::PADDING_RELAXED_PKCS1 back instead of - * RSA::PADDING_PKCS1... that means BER encoding was used. - * - * @access private - * @param string $m - * @param string $s - * @return bool - */ - function _rsassa_pkcs1_v1_5_relaxed_verify($m, $s) - { - // Length checking - - if (strlen($s) != $this->k) { + user_error('Invalid signature'); return false; } @@ -2098,149 +2809,185 @@ class RSA $s = $this->_os2ip($s); $m2 = $this->_rsavp1($s); if ($m2 === false) { + user_error('Invalid signature'); return false; } $em = $this->_i2osp($m2, $this->k); if ($em === false) { + user_error('Invalid signature'); return false; } - if ($this->_string_shift($em, 2) != "\0\1") { + // EMSA-PKCS1-v1_5 encoding + + $em2 = $this->_emsa_pkcs1_v1_5_encode($m, $this->k); + if ($em2 === false) { + user_error('RSA modulus too short'); return false; } - $em = ltrim($em, "\xFF"); - if ($this->_string_shift($em) != "\0") { - return false; - } - - $asn1 = new ASN1(); - $decoded = $asn1->decodeBER($em); - if (!is_array($decoded) || empty($decoded[0]) || strlen($em) > $decoded[0]['length']) { - return false; - } - - $AlgorithmIdentifier = array( - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => array( - 'algorithm' => array('type' => ASN1::TYPE_OBJECT_IDENTIFIER), - 'parameters' => array( - 'type' => ASN1::TYPE_ANY, - 'optional' => true - ) - ) - ); - - $DigestInfo = array( - 'type' => ASN1::TYPE_SEQUENCE, - 'children' => array( - 'digestAlgorithm' => $AlgorithmIdentifier, - 'digest' => array('type' => ASN1::TYPE_OCTET_STRING) - ) - ); - - $oids = array( - '1.2.840.113549.2.2' => 'md2', - '1.2.840.113549.2.4' => 'md4', // from PKCS1 v1.5 - '1.2.840.113549.2.5' => 'md5', - '1.3.14.3.2.26' => 'sha1', - '2.16.840.1.101.3.4.2.1' => 'sha256', - '2.16.840.1.101.3.4.2.2' => 'sha384', - '2.16.840.1.101.3.4.2.3' => 'sha512', - // from PKCS1 v2.2 - '2.16.840.1.101.3.4.2.4' => 'sha224', - '2.16.840.1.101.3.4.2.5' => 'sha512/224', - '2.16.840.1.101.3.4.2.6' => 'sha512/256', - ); - - $asn1->loadOIDs($oids); - - $decoded = $asn1->asn1map($decoded[0], $DigestInfo); - if (!isset($decoded) || $decoded === false) { - return false; - } - - if (!in_array($decoded['digestAlgorithm']['algorithm'], $oids)) { - return false; - } - - $hash = new Hash($decoded['digestAlgorithm']['algorithm']); - $em = $hash->hash($m); - $em2 = base64_decode($decoded['digest']); - + // Compare return $this->_equals($em, $em2); } + /** + * Set Encryption Mode + * + * Valid values include self::ENCRYPTION_OAEP and self::ENCRYPTION_PKCS1. + * + * @access public + * @param Integer $mode + */ + function setEncryptionMode($mode) + { + $this->encryptionMode = $mode; + } + + /** + * Set Signature Mode + * + * Valid values include self::SIGNATURE_PSS and self::SIGNATURE_PKCS1 + * + * @access public + * @param Integer $mode + */ + function setSignatureMode($mode) + { + $this->signatureMode = $mode; + } + + /** + * Set public key comment. + * + * @access public + * @param String $comment + */ + function setComment($comment) + { + $this->comment = $comment; + } + + /** + * Get public key comment. + * + * @access public + * @return String + */ + function getComment() + { + return $this->comment; + } + /** * Encryption * - * Both self::PADDING_OAEP and self::PADDING_PKCS1 both place limits on how long $plaintext can be. + * Both self::ENCRYPTION_OAEP and self::ENCRYPTION_PKCS1 both place limits on how long $plaintext can be. * If $plaintext exceeds those limits it will be broken up so that it does and the resultant ciphertext's will * be concatenated together. * - * @see self::decrypt() + * @see decrypt() * @access public - * @param string $plaintext - * @param int $padding optional - * @return bool|string - * @throws \LengthException if the RSA modulus is too short + * @param String $plaintext + * @return String */ - function encrypt($plaintext, $padding = self::PADDING_OAEP) + function encrypt($plaintext) { - switch ($padding) { - case self::PADDING_NONE: - return $this->_raw_encrypt($plaintext); - case self::PADDING_PKCS15_COMPAT: - case self::PADDING_PKCS1: - return $this->_rsaes_pkcs1_v1_5_encrypt($plaintext, $padding == self::PADDING_PKCS15_COMPAT); - //case self::PADDING_OAEP: + switch ($this->encryptionMode) { + case self::ENCRYPTION_NONE: + $plaintext = str_split($plaintext, $this->k); + $ciphertext = ''; + foreach ($plaintext as $m) { + $ciphertext.= $this->_raw_encrypt($m); + } + return $ciphertext; + case self::ENCRYPTION_PKCS1: + $length = $this->k - 11; + if ($length <= 0) { + return false; + } + + $plaintext = str_split($plaintext, $length); + $ciphertext = ''; + foreach ($plaintext as $m) { + $ciphertext.= $this->_rsaes_pkcs1_v1_5_encrypt($m); + } + return $ciphertext; + //case self::ENCRYPTION_OAEP: default: - return $this->_rsaes_oaep_encrypt($plaintext); + $length = $this->k - 2 * $this->hLen - 2; + if ($length <= 0) { + return false; + } + + $plaintext = str_split($plaintext, $length); + $ciphertext = ''; + foreach ($plaintext as $m) { + $ciphertext.= $this->_rsaes_oaep_encrypt($m); + } + return $ciphertext; } } /** * Decryption * - * @see self::encrypt() + * @see encrypt() * @access public - * @param string $plaintext - * @param int $padding optional - * @return bool|string + * @param String $plaintext + * @return String */ - function decrypt($ciphertext, $padding = self::PADDING_OAEP) + function decrypt($ciphertext) { - switch ($padding) { - case self::PADDING_NONE: - return $this->_raw_encrypt($ciphertext); - case self::PADDING_PKCS1: - return $this->_rsaes_pkcs1_v1_5_decrypt($ciphertext); - //case self::PADDING_OAEP: - default: - return $this->_rsaes_oaep_decrypt($ciphertext); + if ($this->k <= 0) { + return false; } + + $ciphertext = str_split($ciphertext, $this->k); + $ciphertext[count($ciphertext) - 1] = str_pad($ciphertext[count($ciphertext) - 1], $this->k, chr(0), STR_PAD_LEFT); + + $plaintext = ''; + + switch ($this->encryptionMode) { + case self::ENCRYPTION_NONE: + $decrypt = '_raw_encrypt'; + break; + case self::ENCRYPTION_PKCS1: + $decrypt = '_rsaes_pkcs1_v1_5_decrypt'; + break; + //case self::ENCRYPTION_OAEP: + default: + $decrypt = '_rsaes_oaep_decrypt'; + } + + foreach ($ciphertext as $c) { + $temp = $this->$decrypt($c); + if ($temp === false) { + return false; + } + $plaintext.= $temp; + } + + return $plaintext; } /** * Create a signature * - * @see self::verify() + * @see verify() * @access public - * @param string $message - * @param int $padding optional - * @return string + * @param String $message + * @return String */ - function sign($message, $padding = self::PADDING_PSS) + function sign($message) { if (empty($this->modulus) || empty($this->exponent)) { return false; } - switch ($padding) { - case self::PADDING_PKCS1: - case self::PADDING_RELAXED_PKCS1: + switch ($this->signatureMode) { + case self::SIGNATURE_PKCS1: return $this->_rsassa_pkcs1_v1_5_sign($message); - //case self::PADDING_PSS: + //case self::SIGNATURE_PSS: default: return $this->_rsassa_pss_sign($message); } @@ -2249,27 +2996,51 @@ class RSA /** * Verifies a signature * - * @see self::sign() + * @see sign() * @access public - * @param string $message - * @param string $signature - * @param int $padding optional - * @return bool + * @param String $message + * @param String $signature + * @return Boolean */ - function verify($message, $signature, $padding = self::PADDING_PSS) + function verify($message, $signature) { if (empty($this->modulus) || empty($this->exponent)) { return false; } - switch ($padding) { - case self::PADDING_RELAXED_PKCS1: - return $this->_rsassa_pkcs1_v1_5_relaxed_verify($message, $signature); - case self::PADDING_PKCS1: + switch ($this->signatureMode) { + case self::SIGNATURE_PKCS1: return $this->_rsassa_pkcs1_v1_5_verify($message, $signature); - //case self::PADDING_PSS: + //case self::SIGNATURE_PSS: default: return $this->_rsassa_pss_verify($message, $signature); } } + + /** + * Extract raw BER from Base64 encoding + * + * @access private + * @param String $str + * @return String + */ + function _extractBER($str) + { + /* X.509 certs are assumed to be base64 encoded but sometimes they'll have additional things in them + * above and beyond the ceritificate. + * ie. some may have the following preceding the -----BEGIN CERTIFICATE----- line: + * + * Bag Attributes + * localKeyID: 01 00 00 00 + * subject=/O=organization/OU=org unit/CN=common name + * issuer=/O=organization/CN=common name + */ + $temp = preg_replace('#.*?^-+[^-]+-+#ms', '', $str, 1); + // remove the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- stuff + $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; + return $temp != false ? $temp : $str; + } } diff --git a/phpseclib/Crypt/RSA/MSBLOB.php b/phpseclib/Crypt/RSA/MSBLOB.php deleted file mode 100644 index 2f04a1c3..00000000 --- a/phpseclib/Crypt/RSA/MSBLOB.php +++ /dev/null @@ -1,223 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\RSA; - -use phpseclib\Math\BigInteger; - -/** - * Microsoft BLOB Formatted RSA Key Handler - * - * @package RSA - * @author Jim Wigginton - * @access public - */ -class MSBLOB -{ - /**#@+ - * @access private - */ - /** - * Public/Private Key Pair - */ - const PRIVATEKEYBLOB = 0x7; - /** - * Public Key - */ - const PUBLICKEYBLOB = 0x6; - /** - * Public Key - */ - const PUBLICKEYBLOBEX = 0xA; - /** - * RSA public key exchange algorithm - */ - const CALG_RSA_KEYX = 0x0000A400; - /** - * RSA public key exchange algorithm - */ - const CALG_RSA_SIGN = 0x00002400; - /** - * Public Key - */ - const RSA1 = 0x31415352; - /** - * Private Key - */ - const RSA2 = 0x32415352; - /**#@-*/ - - /** - * Break a public or private key down into its constituent components - * - * @access public - * @param string $key - * @param string $password optional - * @return array - */ - static function load($key, $password = '') - { - if (!is_string($key)) { - return false; - } - - $key = base64_decode($key); - - if (!is_string($key) || strlen($key) < 20) { - return false; - } - - // PUBLICKEYSTRUC publickeystruc - // https://msdn.microsoft.com/en-us/library/windows/desktop/aa387453(v=vs.85).aspx - extract(unpack('atype/aversion/vreserved/Valgo', self::_string_shift($key, 8))); - switch (ord($type)) { - case self::PUBLICKEYBLOB: - case self::PUBLICKEYBLOBEX: - $publickey = true; - break; - case self::PRIVATEKEYBLOB: - $publickey = false; - break; - default: - return false; - } - - $components = array('isPublicKey' => $publickey); - - // https://msdn.microsoft.com/en-us/library/windows/desktop/aa375549(v=vs.85).aspx - switch ($algo) { - case self::CALG_RSA_KEYX: - case self::CALG_RSA_SIGN: - break; - default: - return false; - } - - // RSAPUBKEY rsapubkey - // https://msdn.microsoft.com/en-us/library/windows/desktop/aa387685(v=vs.85).aspx - // could do V for pubexp but that's unsigned 32-bit whereas some PHP installs only do signed 32-bit - extract(unpack('Vmagic/Vbitlen/a4pubexp', self::_string_shift($key, 12))); - switch ($magic) { - case self::RSA2: - $components['isPublicKey'] = false; - case self::RSA1: - break; - default: - return false; - } - - $baseLength = $bitlen / 16; - if (strlen($key) != 2 * $baseLength && strlen($key) != 9 * $baseLength) { - return false; - } - - $components[$components['isPublicKey'] ? 'publicExponent' : 'privateExponent'] = new BigInteger(strrev($pubexp), 256); - // BYTE modulus[rsapubkey.bitlen/8] - $components['modulus'] = new BigInteger(strrev(self::_string_shift($key, $bitlen / 8)), 256); - - if ($publickey) { - return $components; - } - - $components['isPublicKey'] = false; - - // BYTE prime1[rsapubkey.bitlen/16] - $components['primes'] = array(1 => new BigInteger(strrev(self::_string_shift($key, $bitlen / 16)), 256)); - // BYTE prime2[rsapubkey.bitlen/16] - $components['primes'][] = new BigInteger(strrev(self::_string_shift($key, $bitlen / 16)), 256); - // BYTE exponent1[rsapubkey.bitlen/16] - $components['exponents'] = array(1 => new BigInteger(strrev(self::_string_shift($key, $bitlen / 16)), 256)); - // BYTE exponent2[rsapubkey.bitlen/16] - $components['exponents'][] = new BigInteger(strrev(self::_string_shift($key, $bitlen / 16)), 256); - // BYTE coefficient[rsapubkey.bitlen/16] - $components['coefficients'] = array(2 => new BigInteger(strrev(self::_string_shift($key, $bitlen / 16)), 256)); - if (isset($components['privateExponent'])) { - $components['publicExponent'] = $components['privateExponent']; - } - // BYTE privateExponent[rsapubkey.bitlen/8] - $components['privateExponent'] = new BigInteger(strrev(self::_string_shift($key, $bitlen / 8)), 256); - - return $components; - } - - /** - * Convert a private key to the appropriate format. - * - * @access public - * @param \phpseclib\Math\BigInteger $n - * @param \phpseclib\Math\BigInteger $e - * @param \phpseclib\Math\BigInteger $d - * @param array $primes - * @param array $exponents - * @param array $coefficients - * @param string $password optional - * @return string - */ - static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, $primes, $exponents, $coefficients, $password = '') - { - $n = strrev($n->toBytes()); - $e = str_pad(strrev($e->toBytes()), 4, "\0"); - $key = pack('aavV', chr(self::PRIVATEKEYBLOB), chr(2), 0, self::CALG_RSA_KEYX); - $key.= pack('VVa*', self::RSA2, 8 * strlen($n), $e); - $key.= $n; - $key.= strrev($primes[1]->toBytes()); - $key.= strrev($primes[2]->toBytes()); - $key.= strrev($exponents[1]->toBytes()); - $key.= strrev($exponents[2]->toBytes()); - $key.= strrev($coefficients[1]->toBytes()); - $key.= strrev($d->toBytes()); - - return base64_encode($key); - } - - /** - * Convert a public key to the appropriate format - * - * @access public - * @param \phpseclib\Math\BigInteger $n - * @param \phpseclib\Math\BigInteger $e - * @return string - */ - static function savePublicKey(BigInteger $n, BigInteger $e) - { - $n = strrev($n->toBytes()); - $e = str_pad(strrev($e->toBytes()), 4, "\0"); - $key = pack('aavV', chr(self::PUBLICKEYBLOB), chr(2), 0, self::CALG_RSA_KEYX); - $key.= pack('VVa*', self::RSA1, 8 * strlen($n), $e); - $key.= $n; - - return base64_encode($key); - } - - /** - * String Shift - * - * Inspired by array_shift - * - * @param string $string - * @param int $index - * @return string - * @access private - */ - static function _string_shift(&$string, $index = 1) - { - $substr = substr($string, 0, $index); - $string = substr($string, $index); - return $substr; - } -} diff --git a/phpseclib/Crypt/RSA/OpenSSH.php b/phpseclib/Crypt/RSA/OpenSSH.php deleted file mode 100644 index 765976ba..00000000 --- a/phpseclib/Crypt/RSA/OpenSSH.php +++ /dev/null @@ -1,140 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\RSA; - -use phpseclib\Math\BigInteger; - -/** - * OpenSSH Formatted RSA Key Handler - * - * @package RSA - * @author Jim Wigginton - * @access public - */ -class OpenSSH -{ - /** - * Default comment - * - * @var string - * @access private - */ - static $comment = 'phpseclib-generated-key'; - - /** - * Sets the default comment - * - * @access public - * @param string $comment - */ - static function setComment($comment) - { - self::$comment = str_replace(array("\r", "\n"), '', $comment); - } - - /** - * Break a public or private key down into its constituent components - * - * @access public - * @param string $key - * @param string $password optional - * @return array - */ - static function load($key, $password = '') - { - if (!is_string($key)) { - return false; - } - - $parts = explode(' ', $key, 3); - - $key = isset($parts[1]) ? base64_decode($parts[1]) : base64_decode($parts[0]); - if ($key === false) { - return false; - } - - $comment = isset($parts[2]) ? $parts[2] : false; - - if (substr($key, 0, 11) != "\0\0\0\7ssh-rsa") { - return false; - } - self::_string_shift($key, 11); - if (strlen($key) <= 4) { - return false; - } - extract(unpack('Nlength', self::_string_shift($key, 4))); - if (strlen($key) <= $length) { - return false; - } - $publicExponent = new BigInteger(self::_string_shift($key, $length), -256); - if (strlen($key) <= 4) { - return false; - } - extract(unpack('Nlength', self::_string_shift($key, 4))); - if (strlen($key) != $length) { - return false; - } - $modulus = new BigInteger(self::_string_shift($key, $length), -256); - - return array( - 'isPublicKey' => true, - 'modulus' => $modulus, - 'publicExponent' => $publicExponent, - 'comment' => $comment - ); - } - - /** - * Convert a public key to the appropriate format - * - * @access public - * @param \phpseclib\Math\BigInteger $n - * @param \phpseclib\Math\BigInteger $e - * @return string - */ - function savePublicKey(BigInteger $n, BigInteger $e) - { - $publicExponent = $e->toBytes(true); - $modulus = $n->toBytes(true); - - // from : - // string "ssh-rsa" - // mpint e - // mpint n - $RSAPublicKey = pack('Na*Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($publicExponent), $publicExponent, strlen($modulus), $modulus); - $RSAPublicKey = 'ssh-rsa ' . base64_encode($RSAPublicKey) . ' ' . self::$comment; - - return $RSAPublicKey; - } - - /** - * String Shift - * - * Inspired by array_shift - * - * @param string $string - * @param int $index - * @return string - * @access private - */ - static function _string_shift(&$string, $index = 1) - { - $substr = substr($string, 0, $index); - $string = substr($string, $index); - return $substr; - } -} diff --git a/phpseclib/Crypt/RSA/PKCS.php b/phpseclib/Crypt/RSA/PKCS.php deleted file mode 100644 index 9d3e6425..00000000 --- a/phpseclib/Crypt/RSA/PKCS.php +++ /dev/null @@ -1,485 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\RSA; - -use phpseclib\Crypt\AES; -use phpseclib\Crypt\Base; -use phpseclib\Crypt\DES; -use phpseclib\Crypt\TripleDES; -use phpseclib\Math\BigInteger; - -/** - * PKCS Formatted RSA Key Handler - * - * @package RSA - * @author Jim Wigginton - * @access public - */ -abstract class PKCS -{ - /**#@+ - * @access private - * @see \phpseclib\Crypt\RSA::createKey() - */ - /** - * ASN1 Integer - */ - const ASN1_INTEGER = 2; - /** - * ASN1 Bit String - */ - const ASN1_BITSTRING = 3; - /** - * ASN1 Octet String - */ - const ASN1_OCTETSTRING = 4; - /** - * ASN1 Object Identifier - */ - const ASN1_OBJECT = 6; - /** - * ASN1 Sequence (with the constucted bit set) - */ - const ASN1_SEQUENCE = 48; - /**#@-*/ - - /**#@+ - * @access private - */ - /** - * Auto-detect the format - */ - const MODE_ANY = 0; - /** - * Require base64-encoded PEM's be supplied - */ - const MODE_PEM = 1; - /** - * Require raw DER's be supplied - */ - const MODE_DER = 2; - /**#@-*/ - - /** - * Is the key a base-64 encoded PEM, DER or should it be auto-detected? - * - * @access private - * @param int - */ - static $format = self::MODE_ANY; - - /** - * Returns the mode constant corresponding to the mode string - * - * @access public - * @param string $mode - * @return int - * @throws \UnexpectedValueException if the block cipher mode is unsupported - */ - static function getEncryptionMode($mode) - { - switch ($mode) { - case 'CBC': - return Base::MODE_CBC; - case 'ECB': - return Base::MODE_ECB; - case 'CFB': - return Base::MODE_CFB; - case 'OFB': - return Base::MODE_OFB; - case 'CTR': - return Base::MODE_CTR; - } - throw new \UnexpectedValueException('Unsupported block cipher mode of operation'); - } - - /** - * Returns a cipher object corresponding to a string - * - * @access public - * @param string $algo - * @return string - * @throws \UnexpectedValueException if the encryption algorithm is unsupported - */ - static function getEncryptionObject($algo) - { - $modes = '(CBC|ECB|CFB|OFB|CTR)'; - switch (true) { - case preg_match("#^AES-(128|192|256)-$modes$#", $algo, $matches): - $cipher = new AES(self::getEncryptionMode($matches[2])); - $cipher->setKeyLength($matches[1]); - return $cipher; - case preg_match("#^DES-EDE3-$modes$#", $algo, $matches): - return new TripleDES(self::getEncryptionMode($matches[1])); - case preg_match("#^DES-$modes$#", $algo, $matches): - return new DES(self::getEncryptionMode($matches[1])); - default: - throw new \UnexpectedValueException('Unsupported encryption algorithmn'); - } - } - - /** - * Generate a symmetric key for PKCS#1 keys - * - * @access public - * @param string $password - * @param string $iv - * @param int $length - * @return string - */ - static function generateSymmetricKey($password, $iv, $length) - { - $symkey = ''; - $iv = substr($iv, 0, 8); - while (strlen($symkey) < $length) { - $symkey.= pack('H*', md5($symkey . $password . $iv)); - } - return substr($symkey, 0, $length); - } - - /** - * Break a public or private key down into its constituent components - * - * @access public - * @param string $key - * @param string $password optional - * @return array - */ - static function load($key, $password = '') - { - if (!is_string($key)) { - return false; - } - - $components = array('isPublicKey' => strpos($key, 'PUBLIC') !== false); - - /* Although PKCS#1 proposes a format that public and private keys can use, encrypting them is - "outside the scope" of PKCS#1. PKCS#1 then refers you to PKCS#12 and PKCS#15 if you're wanting to - protect private keys, however, that's not what OpenSSL* does. OpenSSL protects private keys by adding - two new "fields" to the key - DEK-Info and Proc-Type. These fields are discussed here: - - http://tools.ietf.org/html/rfc1421#section-4.6.1.1 - http://tools.ietf.org/html/rfc1421#section-4.6.1.3 - - DES-EDE3-CBC as an algorithm, however, is not discussed anywhere, near as I can tell. - DES-CBC and DES-EDE are discussed in RFC1423, however, DES-EDE3-CBC isn't, nor is its key derivation - function. As is, the definitive authority on this encoding scheme isn't the IETF but rather OpenSSL's - own implementation. ie. the implementation *is* the standard and any bugs that may exist in that - implementation are part of the standard, as well. - - * OpenSSL is the de facto standard. It's utilized by OpenSSH and other projects */ - if (preg_match('#DEK-Info: (.+),(.+)#', $key, $matches)) { - $iv = pack('H*', trim($matches[2])); - // remove the Proc-Type / DEK-Info sections as they're no longer needed - $key = preg_replace('#^(?:Proc-Type|DEK-Info): .*#m', '', $key); - $ciphertext = self::_extractBER($key); - if ($ciphertext === false) { - $ciphertext = $key; - } - $crypto = self::getEncryptionObject($matches[1]); - $crypto->setKey(self::generateSymmetricKey($password, $iv, $crypto->getKeyLength() >> 3)); - $crypto->setIV($iv); - $key = $crypto->decrypt($ciphertext); - if ($key === false) { - return false; - } - } else { - if (self::$format != self::MODE_DER) { - $decoded = self::_extractBER($key); - if ($decoded !== false) { - $key = $decoded; - } elseif (self::$format == self::MODE_PEM) { - return false; - } - } - } - - if (ord(self::_string_shift($key)) != self::ASN1_SEQUENCE) { - return false; - } - if (self::_decodeLength($key) != strlen($key)) { - return false; - } - - $tag = ord(self::_string_shift($key)); - /* intended for keys for which OpenSSL's asn1parse returns the following: - - 0:d=0 hl=4 l= 631 cons: SEQUENCE - 4:d=1 hl=2 l= 1 prim: INTEGER :00 - 7:d=1 hl=2 l= 13 cons: SEQUENCE - 9:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption - 20:d=2 hl=2 l= 0 prim: NULL - 22:d=1 hl=4 l= 609 prim: OCTET STRING - - ie. PKCS8 keys */ - - if ($tag == self::ASN1_INTEGER && substr($key, 0, 3) == "\x01\x00\x30") { - self::_string_shift($key, 3); - $tag = self::ASN1_SEQUENCE; - } - - if ($tag == self::ASN1_SEQUENCE) { - $temp = self::_string_shift($key, self::_decodeLength($key)); - if (ord(self::_string_shift($temp)) != self::ASN1_OBJECT) { - return false; - } - $length = self::_decodeLength($temp); - switch (self::_string_shift($temp, $length)) { - case "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01": // rsaEncryption - break; - case "\x2a\x86\x48\x86\xf7\x0d\x01\x05\x03": // pbeWithMD5AndDES-CBC - /* - PBEParameter ::= SEQUENCE { - salt OCTET STRING (SIZE(8)), - iterationCount INTEGER } - */ - if (ord(self::_string_shift($temp)) != self::ASN1_SEQUENCE) { - return false; - } - if (self::_decodeLength($temp) != strlen($temp)) { - return false; - } - self::_string_shift($temp); // assume it's an octet string - $salt = self::_string_shift($temp, self::_decodeLength($temp)); - if (ord(self::_string_shift($temp)) != self::ASN1_INTEGER) { - return false; - } - self::_decodeLength($temp); - list(, $iterationCount) = unpack('N', str_pad($temp, 4, chr(0), STR_PAD_LEFT)); - self::_string_shift($key); // assume it's an octet string - $length = self::_decodeLength($key); - if (strlen($key) != $length) { - return false; - } - - $crypto = new DES(DES::MODE_CBC); - $crypto->setPassword($password, 'pbkdf1', 'md5', $salt, $iterationCount); - $key = $crypto->decrypt($key); - if ($key === false) { - return false; - } - return self::load($key); - default: - return false; - } - /* intended for keys for which OpenSSL's asn1parse returns the following: - - 0:d=0 hl=4 l= 290 cons: SEQUENCE - 4:d=1 hl=2 l= 13 cons: SEQUENCE - 6:d=2 hl=2 l= 9 prim: OBJECT :rsaEncryption - 17:d=2 hl=2 l= 0 prim: NULL - 19:d=1 hl=4 l= 271 prim: BIT STRING */ - $tag = ord(self::_string_shift($key)); // skip over the BIT STRING / OCTET STRING tag - self::_decodeLength($key); // skip over the BIT STRING / OCTET STRING length - // "The initial octet shall encode, as an unsigned binary integer wtih bit 1 as the least significant bit, the number of - // unused bits in the final subsequent octet. The number shall be in the range zero to seven." - // -- http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf (section 8.6.2.2) - if ($tag == self::ASN1_BITSTRING) { - self::_string_shift($key); - } - if (ord(self::_string_shift($key)) != self::ASN1_SEQUENCE) { - return false; - } - if (self::_decodeLength($key) != strlen($key)) { - return false; - } - $tag = ord(self::_string_shift($key)); - } - if ($tag != self::ASN1_INTEGER) { - return false; - } - - $length = self::_decodeLength($key); - $temp = self::_string_shift($key, $length); - if (strlen($temp) != 1 || ord($temp) > 2) { - $components['modulus'] = new BigInteger($temp, 256); - self::_string_shift($key); // skip over self::ASN1_INTEGER - $length = self::_decodeLength($key); - $components[$components['isPublicKey'] ? 'publicExponent' : 'privateExponent'] = new BigInteger(self::_string_shift($key, $length), 256); - - return $components; - } - if (ord(self::_string_shift($key)) != self::ASN1_INTEGER) { - return false; - } - $length = self::_decodeLength($key); - $components['modulus'] = new BigInteger(self::_string_shift($key, $length), 256); - self::_string_shift($key); - $length = self::_decodeLength($key); - $components['publicExponent'] = new BigInteger(self::_string_shift($key, $length), 256); - self::_string_shift($key); - $length = self::_decodeLength($key); - $components['privateExponent'] = new BigInteger(self::_string_shift($key, $length), 256); - self::_string_shift($key); - $length = self::_decodeLength($key); - $components['primes'] = array(1 => new BigInteger(self::_string_shift($key, $length), 256)); - self::_string_shift($key); - $length = self::_decodeLength($key); - $components['primes'][] = new BigInteger(self::_string_shift($key, $length), 256); - self::_string_shift($key); - $length = self::_decodeLength($key); - $components['exponents'] = array(1 => new BigInteger(self::_string_shift($key, $length), 256)); - self::_string_shift($key); - $length = self::_decodeLength($key); - $components['exponents'][] = new BigInteger(self::_string_shift($key, $length), 256); - self::_string_shift($key); - $length = self::_decodeLength($key); - $components['coefficients'] = array(2 => new BigInteger(self::_string_shift($key, $length), 256)); - - if (!empty($key)) { - if (ord(self::_string_shift($key)) != self::ASN1_SEQUENCE) { - return false; - } - self::_decodeLength($key); - while (!empty($key)) { - if (ord(self::_string_shift($key)) != self::ASN1_SEQUENCE) { - return false; - } - self::_decodeLength($key); - $key = substr($key, 1); - $length = self::_decodeLength($key); - $components['primes'][] = new BigInteger(self::_string_shift($key, $length), 256); - self::_string_shift($key); - $length = self::_decodeLength($key); - $components['exponents'][] = new BigInteger(self::_string_shift($key, $length), 256); - self::_string_shift($key); - $length = self::_decodeLength($key); - $components['coefficients'][] = new BigInteger(self::_string_shift($key, $length), 256); - } - } - - return $components; - } - - /** - * Require base64-encoded PEM's be supplied - * - * @see self::load() - * @access public - */ - static function requirePEM() - { - self::$format = self::MODE_PEM; - } - - /** - * Require raw DER's be supplied - * - * @see self::load() - * @access public - */ - static function requireDER() - { - self::$format = self::MODE_DER; - } - - /** - * Accept any format and auto detect the format - * - * This is the default setting - * - * @see self::load() - * @access public - */ - static function requireAny() - { - self::$format = self::MODE_ANY; - } - - /** - * DER-decode the length - * - * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See - * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information. - * - * @access private - * @param string $string - * @return int - */ - static function _decodeLength(&$string) - { - $length = ord(self::_string_shift($string)); - if ($length & 0x80) { // definite length, long form - $length&= 0x7F; - $temp = self::_string_shift($string, $length); - list(, $length) = unpack('N', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4)); - } - return $length; - } - - /** - * DER-encode the length - * - * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See - * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information. - * - * @access private - * @param int $length - * @return string - */ - static function _encodeLength($length) - { - if ($length <= 0x7F) { - return chr($length); - } - - $temp = ltrim(pack('N', $length), chr(0)); - return pack('Ca*', 0x80 | strlen($temp), $temp); - } - - /** - * String Shift - * - * Inspired by array_shift - * - * @param string $string - * @param int $index - * @return string - * @access private - */ - static function _string_shift(&$string, $index = 1) - { - $substr = substr($string, 0, $index); - $string = substr($string, $index); - return $substr; - } - - /** - * Extract raw BER from Base64 encoding - * - * @access private - * @param string $str - * @return string - */ - static function _extractBER($str) - { - /* X.509 certs are assumed to be base64 encoded but sometimes they'll have additional things in them - * above and beyond the ceritificate. - * ie. some may have the following preceding the -----BEGIN CERTIFICATE----- line: - * - * Bag Attributes - * localKeyID: 01 00 00 00 - * subject=/O=organization/OU=org unit/CN=common name - * issuer=/O=organization/CN=common name - */ - $temp = preg_replace('#.*?^-+[^-]+-+[\r\n ]*$#ms', '', $str, 1); - // remove the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- stuff - $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; - return $temp != false ? $temp : $str; - } -} diff --git a/phpseclib/Crypt/RSA/PKCS1.php b/phpseclib/Crypt/RSA/PKCS1.php deleted file mode 100644 index ae208d15..00000000 --- a/phpseclib/Crypt/RSA/PKCS1.php +++ /dev/null @@ -1,172 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\RSA; - -use phpseclib\Crypt\AES; -use phpseclib\Crypt\DES; -use phpseclib\Crypt\Random; -use phpseclib\Crypt\TripleDES; -use phpseclib\Math\BigInteger; - -/** - * PKCS#1 Formatted RSA Key Handler - * - * @package RSA - * @author Jim Wigginton - * @access public - */ -class PKCS1 extends PKCS -{ - /** - * Default encryption algorithm - * - * @var string - * @access private - */ - static $defaultEncryptionAlgorithm = 'DES-EDE3-CBC'; - - /** - * Sets the default encryption algorithm - * - * @access public - * @param string $algo - */ - static function setEncryptionAlgorithm($algo) - { - self::$defaultEncryptionAlgorithm = $algo; - } - - /** - * Convert a private key to the appropriate format. - * - * @access public - * @param \phpseclib\Math\BigInteger $n - * @param \phpseclib\Math\BigInteger $e - * @param \phpseclib\Math\BigInteger $d - * @param array $primes - * @param array $exponents - * @param array $coefficients - * @param string $password optional - * @return string - */ - static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, $primes, $exponents, $coefficients, $password = '') - { - $num_primes = count($primes); - $raw = array( - 'version' => $num_primes == 2 ? chr(0) : chr(1), // two-prime vs. multi - 'modulus' => $n->toBytes(true), - 'publicExponent' => $e->toBytes(true), - 'privateExponent' => $d->toBytes(true), - 'prime1' => $primes[1]->toBytes(true), - 'prime2' => $primes[2]->toBytes(true), - 'exponent1' => $exponents[1]->toBytes(true), - 'exponent2' => $exponents[2]->toBytes(true), - 'coefficient' => $coefficients[2]->toBytes(true) - ); - - $components = array(); - foreach ($raw as $name => $value) { - $components[$name] = pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($value)), $value); - } - - $RSAPrivateKey = implode('', $components); - - if ($num_primes > 2) { - $OtherPrimeInfos = ''; - for ($i = 3; $i <= $num_primes; $i++) { - // OtherPrimeInfos ::= SEQUENCE SIZE(1..MAX) OF OtherPrimeInfo - // - // OtherPrimeInfo ::= SEQUENCE { - // prime INTEGER, -- ri - // exponent INTEGER, -- di - // coefficient INTEGER -- ti - // } - $OtherPrimeInfo = pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($primes[$i]->toBytes(true))), $primes[$i]->toBytes(true)); - $OtherPrimeInfo.= pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($exponents[$i]->toBytes(true))), $exponents[$i]->toBytes(true)); - $OtherPrimeInfo.= pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($coefficients[$i]->toBytes(true))), $coefficients[$i]->toBytes(true)); - $OtherPrimeInfos.= pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($OtherPrimeInfo)), $OtherPrimeInfo); - } - $RSAPrivateKey.= pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($OtherPrimeInfos)), $OtherPrimeInfos); - } - - $RSAPrivateKey = pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey); - - if (!empty($password) || is_string($password)) { - $cipher = self::getEncryptionObject(self::$defaultEncryptionAlgorithm); - $iv = Random::string($cipher->getBlockLength() >> 3); - $cipher->setKey(self::generateSymmetricKey($password, $iv, $cipher->getKeyLength() >> 3)); - $cipher->setIV($iv); - $iv = strtoupper(bin2hex($iv)); - $RSAPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\r\n" . - "Proc-Type: 4,ENCRYPTED\r\n" . - "DEK-Info: " . self::$defaultEncryptionAlgorithm . ",$iv\r\n" . - "\r\n" . - chunk_split(base64_encode($cipher->encrypt($RSAPrivateKey)), 64) . - '-----END RSA PRIVATE KEY-----'; - } else { - $RSAPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\r\n" . - chunk_split(base64_encode($RSAPrivateKey), 64) . - '-----END RSA PRIVATE KEY-----'; - } - - return $RSAPrivateKey; - } - - /** - * Convert a public key to the appropriate format - * - * @access public - * @param \phpseclib\Math\BigInteger $n - * @param \phpseclib\Math\BigInteger $e - * @return string - */ - static function savePublicKey(BigInteger $n, BigInteger $e) - { - $modulus = $n->toBytes(true); - $publicExponent = $e->toBytes(true); - - // from : - // RSAPublicKey ::= SEQUENCE { - // modulus INTEGER, -- n - // publicExponent INTEGER -- e - // } - $components = array( - 'modulus' => pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($modulus)), $modulus), - 'publicExponent' => pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($publicExponent)), $publicExponent) - ); - - $RSAPublicKey = pack( - 'Ca*a*a*', - self::ASN1_SEQUENCE, - self::_encodeLength(strlen($components['modulus']) + strlen($components['publicExponent'])), - $components['modulus'], - $components['publicExponent'] - ); - - $RSAPublicKey = "-----BEGIN RSA PUBLIC KEY-----\r\n" . - chunk_split(base64_encode($RSAPublicKey), 64) . - '-----END RSA PUBLIC KEY-----'; - - return $RSAPublicKey; - } -} diff --git a/phpseclib/Crypt/RSA/PKCS8.php b/phpseclib/Crypt/RSA/PKCS8.php deleted file mode 100644 index 164fca19..00000000 --- a/phpseclib/Crypt/RSA/PKCS8.php +++ /dev/null @@ -1,208 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\RSA; - -use phpseclib\Crypt\DES; -use phpseclib\Crypt\Random; -use phpseclib\Math\BigInteger; - -/** - * PKCS#8 Formatted RSA Key Handler - * - * @package RSA - * @author Jim Wigginton - * @access public - */ -class PKCS8 extends PKCS -{ - /** - * Convert a private key to the appropriate format. - * - * @access public - * @param \phpseclib\Math\BigInteger $n - * @param \phpseclib\Math\BigInteger $e - * @param \phpseclib\Math\BigInteger $d - * @param array $primes - * @param array $exponents - * @param array $coefficients - * @param string $password optional - * @return string - */ - static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, $primes, $exponents, $coefficients, $password = '') - { - $num_primes = count($primes); - $raw = array( - 'version' => $num_primes == 2 ? chr(0) : chr(1), // two-prime vs. multi - 'modulus' => $n->toBytes(true), - 'publicExponent' => $e->toBytes(true), - 'privateExponent' => $d->toBytes(true), - 'prime1' => $primes[1]->toBytes(true), - 'prime2' => $primes[2]->toBytes(true), - 'exponent1' => $exponents[1]->toBytes(true), - 'exponent2' => $exponents[2]->toBytes(true), - 'coefficient' => $coefficients[2]->toBytes(true) - ); - - $components = array(); - foreach ($raw as $name => $value) { - $components[$name] = pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($value)), $value); - } - - $RSAPrivateKey = implode('', $components); - - if ($num_primes > 2) { - $OtherPrimeInfos = ''; - for ($i = 3; $i <= $num_primes; $i++) { - // OtherPrimeInfos ::= SEQUENCE SIZE(1..MAX) OF OtherPrimeInfo - // - // OtherPrimeInfo ::= SEQUENCE { - // prime INTEGER, -- ri - // exponent INTEGER, -- di - // coefficient INTEGER -- ti - // } - $OtherPrimeInfo = pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($primes[$i]->toBytes(true))), $primes[$i]->toBytes(true)); - $OtherPrimeInfo.= pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($exponents[$i]->toBytes(true))), $exponents[$i]->toBytes(true)); - $OtherPrimeInfo.= pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($coefficients[$i]->toBytes(true))), $coefficients[$i]->toBytes(true)); - $OtherPrimeInfos.= pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($OtherPrimeInfo)), $OtherPrimeInfo); - } - $RSAPrivateKey.= pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($OtherPrimeInfos)), $OtherPrimeInfos); - } - - $RSAPrivateKey = pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey); - - $rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA - $RSAPrivateKey = pack( - 'Ca*a*Ca*a*', - self::ASN1_INTEGER, - "\01\00", - $rsaOID, - 4, - self::_encodeLength(strlen($RSAPrivateKey)), - $RSAPrivateKey - ); - $RSAPrivateKey = pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey); - if (!empty($password) || is_string($password)) { - $salt = Random::string(8); - $iterationCount = 2048; - - $crypto = new DES(DES::MODE_CBC); - $crypto->setPassword($password, 'pbkdf1', 'md5', $salt, $iterationCount); - $RSAPrivateKey = $crypto->encrypt($RSAPrivateKey); - - $parameters = pack( - 'Ca*a*Ca*N', - self::ASN1_OCTETSTRING, - self::_encodeLength(strlen($salt)), - $salt, - self::ASN1_INTEGER, - self::_encodeLength(4), - $iterationCount - ); - $pbeWithMD5AndDES_CBC = "\x2a\x86\x48\x86\xf7\x0d\x01\x05\x03"; - - $encryptionAlgorithm = pack( - 'Ca*a*Ca*a*', - self::ASN1_OBJECT, - self::_encodeLength(strlen($pbeWithMD5AndDES_CBC)), - $pbeWithMD5AndDES_CBC, - self::ASN1_SEQUENCE, - self::_encodeLength(strlen($parameters)), - $parameters - ); - - $RSAPrivateKey = pack( - 'Ca*a*Ca*a*', - self::ASN1_SEQUENCE, - self::_encodeLength(strlen($encryptionAlgorithm)), - $encryptionAlgorithm, - self::ASN1_OCTETSTRING, - self::_encodeLength(strlen($RSAPrivateKey)), - $RSAPrivateKey - ); - - $RSAPrivateKey = pack('Ca*a*', self::ASN1_SEQUENCE, self::_encodeLength(strlen($RSAPrivateKey)), $RSAPrivateKey); - - $RSAPrivateKey = "-----BEGIN ENCRYPTED PRIVATE KEY-----\r\n" . - chunk_split(base64_encode($RSAPrivateKey), 64) . - '-----END ENCRYPTED PRIVATE KEY-----'; - } else { - $RSAPrivateKey = "-----BEGIN PRIVATE KEY-----\r\n" . - chunk_split(base64_encode($RSAPrivateKey), 64) . - '-----END PRIVATE KEY-----'; - } - - return $RSAPrivateKey; - } - - /** - * Convert a public key to the appropriate format - * - * @access public - * @param \phpseclib\Math\BigInteger $n - * @param \phpseclib\Math\BigInteger $e - * @return string - */ - static function savePublicKey(BigInteger $n, BigInteger $e) - { - $modulus = $n->toBytes(true); - $publicExponent = $e->toBytes(true); - - // from : - // RSAPublicKey ::= SEQUENCE { - // modulus INTEGER, -- n - // publicExponent INTEGER -- e - // } - $components = array( - 'modulus' => pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($modulus)), $modulus), - 'publicExponent' => pack('Ca*a*', self::ASN1_INTEGER, self::_encodeLength(strlen($publicExponent)), $publicExponent) - ); - - $RSAPublicKey = pack( - 'Ca*a*a*', - self::ASN1_SEQUENCE, - self::_encodeLength(strlen($components['modulus']) + strlen($components['publicExponent'])), - $components['modulus'], - $components['publicExponent'] - ); - - // sequence(oid(1.2.840.113549.1.1.1), null)) = rsaEncryption. - $rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA - $RSAPublicKey = chr(0) . $RSAPublicKey; - $RSAPublicKey = chr(3) . self::_encodeLength(strlen($RSAPublicKey)) . $RSAPublicKey; - - $RSAPublicKey = pack( - 'Ca*a*', - self::ASN1_SEQUENCE, - self::_encodeLength(strlen($rsaOID . $RSAPublicKey)), - $rsaOID . $RSAPublicKey - ); - - $RSAPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" . - chunk_split(base64_encode($RSAPublicKey), 64) . - '-----END PUBLIC KEY-----'; - - return $RSAPublicKey; - } -} diff --git a/phpseclib/Crypt/RSA/PuTTY.php b/phpseclib/Crypt/RSA/PuTTY.php deleted file mode 100644 index 302eb2b1..00000000 --- a/phpseclib/Crypt/RSA/PuTTY.php +++ /dev/null @@ -1,311 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\RSA; - -use phpseclib\Crypt\AES; -use phpseclib\Crypt\Hash; -use phpseclib\Math\BigInteger; - -/** - * PuTTY Formatted RSA Key Handler - * - * @package RSA - * @author Jim Wigginton - * @access public - */ -class PuTTY -{ - /** - * Default comment - * - * @var string - * @access private - */ - static $comment = 'phpseclib-generated-key'; - - /** - * Sets the default comment - * - * @access public - * @param string $comment - */ - static function setComment($comment) - { - self::$comment = str_replace(array("\r", "\n"), '', $comment); - } - - /** - * Generate a symmetric key for PuTTY keys - * - * @access public - * @param string $password - * @param string $iv - * @param int $length - * @return string - */ - static function generateSymmetricKey($password, $length) - { - $symkey = ''; - $sequence = 0; - while (strlen($symkey) < $length) { - $temp = pack('Na*', $sequence++, $password); - $symkey.= pack('H*', sha1($temp)); - } - return substr($symkey, 0, $length); - } - - /** - * Break a public or private key down into its constituent components - * - * @access public - * @param string $key - * @param string $password optional - * @return array - */ - static function load($key, $password = '') - { - if (!is_string($key)) { - return false; - } - - static $one; - if (!isset($one)) { - $one = new BigInteger(1); - } - - if (strpos($key, 'BEGIN SSH2 PUBLIC KEY')) { - $data = preg_split('#[\r\n]+#', $key); - $data = array_splice($data, 2, -1); - $data = implode('', $data); - - $components = OpenSSH::load($data); - if ($components === false) { - return false; - } - - if (!preg_match('#Comment: "(.+)"#', $key, $matches)) { - return false; - } - $components['comment'] = str_replace(array('\\\\', '\"'), array('\\', '"'), $matches[1]); - - return $components; - } - - $components = array('isPublicKey' => false); - $key = preg_split('#\r\n|\r|\n#', $key); - $type = trim(preg_replace('#PuTTY-User-Key-File-2: (.+)#', '$1', $key[0])); - if ($type != 'ssh-rsa') { - return false; - } - $encryption = trim(preg_replace('#Encryption: (.+)#', '$1', $key[1])); - $components['comment'] = trim(preg_replace('#Comment: (.+)#', '$1', $key[2])); - - $publicLength = trim(preg_replace('#Public-Lines: (\d+)#', '$1', $key[3])); - $public = base64_decode(implode('', array_map('trim', array_slice($key, 4, $publicLength)))); - $public = substr($public, 11); - extract(unpack('Nlength', self::_string_shift($public, 4))); - $components['publicExponent'] = new BigInteger(self::_string_shift($public, $length), -256); - extract(unpack('Nlength', self::_string_shift($public, 4))); - $components['modulus'] = new BigInteger(self::_string_shift($public, $length), -256); - - $privateLength = trim(preg_replace('#Private-Lines: (\d+)#', '$1', $key[$publicLength + 4])); - $private = base64_decode(implode('', array_map('trim', array_slice($key, $publicLength + 5, $privateLength)))); - - switch ($encryption) { - case 'aes256-cbc': - $symkey = static::generateSymmetricKey($password, 32); - $crypto = new AES(AES::MODE_CBC); - } - - if ($encryption != 'none') { - $crypto->setKey($symkey); - $crypto->setIV(str_repeat("\0", $crypto->getBlockLength() >> 3)); - $crypto->disablePadding(); - $private = $crypto->decrypt($private); - if ($private === false) { - return false; - } - } - - extract(unpack('Nlength', self::_string_shift($private, 4))); - if (strlen($private) < $length) { - return false; - } - $components['privateExponent'] = new BigInteger(self::_string_shift($private, $length), -256); - extract(unpack('Nlength', self::_string_shift($private, 4))); - if (strlen($private) < $length) { - return false; - } - $components['primes'] = array(1 => new BigInteger(self::_string_shift($private, $length), -256)); - extract(unpack('Nlength', self::_string_shift($private, 4))); - if (strlen($private) < $length) { - return false; - } - $components['primes'][] = new BigInteger(self::_string_shift($private, $length), -256); - - $temp = $components['primes'][1]->subtract($one); - $components['exponents'] = array(1 => $components['publicExponent']->modInverse($temp)); - $temp = $components['primes'][2]->subtract($one); - $components['exponents'][] = $components['publicExponent']->modInverse($temp); - - extract(unpack('Nlength', self::_string_shift($private, 4))); - if (strlen($private) < $length) { - return false; - } - $components['coefficients'] = array(2 => new BigInteger(self::_string_shift($private, $length), -256)); - - return $components; - } - - /** - * String Shift - * - * Inspired by array_shift - * - * @param string $string - * @param int $index - * @return string - * @access private - */ - static function _string_shift(&$string, $index = 1) - { - $substr = substr($string, 0, $index); - $string = substr($string, $index); - return $substr; - } - - /** - * Convert a private key to the appropriate format. - * - * @access public - * @param \phpseclib\Math\BigInteger $n - * @param \phpseclib\Math\BigInteger $e - * @param \phpseclib\Math\BigInteger $d - * @param array $primes - * @param array $exponents - * @param array $coefficients - * @param string $password optional - * @return string - */ - static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, $primes, $exponents, $coefficients, $password = '') - { - if (count($primes) != 2) { - return false; - } - - $raw = array( - 'modulus' => $n->toBytes(true), - 'publicExponent' => $e->toBytes(true), - 'privateExponent' => $d->toBytes(true), - 'prime1' => $primes[1]->toBytes(true), - 'prime2' => $primes[2]->toBytes(true), - 'exponent1' => $exponents[1]->toBytes(true), - 'exponent2' => $exponents[2]->toBytes(true), - 'coefficient' => $coefficients[2]->toBytes(true) - ); - - $key = "PuTTY-User-Key-File-2: ssh-rsa\r\nEncryption: "; - $encryption = (!empty($password) || is_string($password)) ? 'aes256-cbc' : 'none'; - $key.= $encryption; - $key.= "\r\nComment: " . self::$comment . "\r\n"; - $public = pack( - 'Na*Na*Na*', - strlen('ssh-rsa'), - 'ssh-rsa', - strlen($raw['publicExponent']), - $raw['publicExponent'], - strlen($raw['modulus']), - $raw['modulus'] - ); - $source = pack( - 'Na*Na*Na*Na*', - strlen('ssh-rsa'), - 'ssh-rsa', - strlen($encryption), - $encryption, - strlen(self::$comment), - self::$comment, - strlen($public), - $public - ); - $public = base64_encode($public); - $key.= "Public-Lines: " . ((strlen($public) + 63) >> 6) . "\r\n"; - $key.= chunk_split($public, 64); - $private = pack( - 'Na*Na*Na*Na*', - strlen($raw['privateExponent']), - $raw['privateExponent'], - strlen($raw['prime1']), - $raw['prime1'], - strlen($raw['prime2']), - $raw['prime2'], - strlen($raw['coefficient']), - $raw['coefficient'] - ); - if (empty($password) && !is_string($password)) { - $source.= pack('Na*', strlen($private), $private); - $hashkey = 'putty-private-key-file-mac-key'; - } else { - $private.= Random::string(16 - (strlen($private) & 15)); - $source.= pack('Na*', strlen($private), $private); - $crypto = new AES(); - - $crypto->setKey(static::generateSymmetricKey($password, 32)); - $crypto->setIV(str_repeat("\0", $crypto->getBlockLength() >> 3)); - $crypto->disablePadding(); - $private = $crypto->encrypt($private); - $hashkey = 'putty-private-key-file-mac-key' . $password; - } - - $private = base64_encode($private); - $key.= 'Private-Lines: ' . ((strlen($private) + 63) >> 6) . "\r\n"; - $key.= chunk_split($private, 64); - $hash = new Hash('sha1'); - $hash->setKey(pack('H*', sha1($hashkey))); - $key.= 'Private-MAC: ' . bin2hex($hash->hash($source)) . "\r\n"; - - return $key; - } - - /** - * Convert a public key to the appropriate format - * - * @access public - * @param \phpseclib\Math\BigInteger $n - * @param \phpseclib\Math\BigInteger $e - * @return string - */ - static function savePublicKey(BigInteger $n, BigInteger $e) - { - $n = $n->toBytes(true); - $e = $e->toBytes(true); - - $key = pack( - 'Na*Na*Na*', - strlen('ssh-rsa'), - 'ssh-rsa', - strlen($e), - $e, - strlen($n), - $n - ); - $key = "---- BEGIN SSH2 PUBLIC KEY ----\r\n" . - 'Comment: "' . str_replace(array('\\', '"'), array('\\\\', '\"'), self::$comment) . "\"\r\n"; - chunk_split(base64_encode($key), 64) . - '---- END SSH2 PUBLIC KEY ----'; - - return $key; - } -} diff --git a/phpseclib/Crypt/RSA/Raw.php b/phpseclib/Crypt/RSA/Raw.php deleted file mode 100644 index d3992521..00000000 --- a/phpseclib/Crypt/RSA/Raw.php +++ /dev/null @@ -1,103 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\RSA; - -use phpseclib\Math\BigInteger; - -/** - * Raw RSA Key Handler - * - * @package RSA - * @author Jim Wigginton - * @access public - */ -class Raw -{ - /** - * Break a public or private key down into its constituent components - * - * @access public - * @param string $key - * @param string $password optional - * @return array - */ - static function load($key, $password = '') - { - if (!is_array($key)) { - return false; - } - if (isset($key['isPublicKey']) && isset($key['modulus'])) { - if (isset($key['privateExponent']) || isset($key['publicExponent'])) { - if (!isset($key['primes'])) { - return $key; - } - if (isset($key['exponents']) && isset($key['coefficients']) && isset($key['publicExponent']) && isset($key['privateExponent'])) { - return $key; - } - } - } - $components = array('isPublicKey' => true); - switch (true) { - case isset($key['e']): - $components['publicExponent'] = $key['e']; - break; - case isset($key['exponent']): - $components['publicExponent'] = $key['exponent']; - break; - case isset($key['publicExponent']): - $components['publicExponent'] = $key['publicExponent']; - break; - case isset($key[0]): - $components['publicExponent'] = $key[0]; - } - switch (true) { - case isset($key['n']): - $components['modulus'] = $key['n']; - break; - case isset($key['modulo']): - $components['modulus'] = $key['modulo']; - break; - case isset($key['modulus']): - $components['modulus'] = $key['modulus']; - break; - case isset($key[1]): - $components['modulus'] = $key[1]; - } - return isset($components['modulus']) && isset($components['publicExponent']) ? $components : false; - } - - /** - * Convert a public key to the appropriate format - * - * @access public - * @param \phpseclib\Math\BigInteger $n - * @param \phpseclib\Math\BigInteger $e - * @return string - */ - static function savePublicKey(BigInteger $n, BigInteger $e) - { - return array('e' => clone $e, 'n' => clone $n); - } -} diff --git a/phpseclib/Crypt/RSA/XML.php b/phpseclib/Crypt/RSA/XML.php deleted file mode 100644 index 00b4d910..00000000 --- a/phpseclib/Crypt/RSA/XML.php +++ /dev/null @@ -1,146 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Crypt\RSA; - -use phpseclib\Math\BigInteger; - -/** - * XML Formatted RSA Key Handler - * - * @package RSA - * @author Jim Wigginton - * @access public - */ -class XML -{ - /** - * Break a public or private key down into its constituent components - * - * @access public - * @param string $key - * @param string $password optional - * @return array - */ - static function load($key, $password = '') - { - if (!is_string($key)) { - return false; - } - - $components = array( - 'isPublicKey' => false, - 'primes' => array(), - 'exponents' => array(), - 'coefficients' => array() - ); - - $use_errors = libxml_use_internal_errors(true); - - $dom = new \DOMDocument(); - if (!$dom->loadXML('' . $key . '')) { - return false; - } - $xpath = new \DOMXPath($dom); - $keys = array('modulus', 'exponent', 'p', 'q', 'dp', 'dq', 'inverseq', 'd'); - foreach ($keys as $key) { - // $dom->getElementsByTagName($key) is case-sensitive - $temp = $xpath->query("//*[translate(local-name(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='$key']"); - if (!$temp->length) { - continue; - } - $value = new BigInteger(base64_decode($temp->item(0)->nodeValue), 256); - switch ($key) { - case 'modulus': - $components['modulus'] = $value; - break; - case 'exponent': - $components['publicExponent'] = $value; - break; - case 'p': - $components['primes'][1] = $value; - break; - case 'q': - $components['primes'][2] = $value; - break; - case 'dp': - $components['exponents'][1] = $value; - break; - case 'dq': - $components['exponents'][2] = $value; - break; - case 'inverseq': - $components['coefficients'][2] = $value; - break; - case 'd': - $components['privateExponent'] = $value; - } - } - - libxml_use_internal_errors($use_errors); - - return isset($components['modulus']) && isset($components['publicExponent']) ? $components : false; - } - - /** - * Convert a private key to the appropriate format. - * - * @access public - * @param \phpseclib\Math\BigInteger $n - * @param \phpseclib\Math\BigInteger $e - * @param \phpseclib\Math\BigInteger $d - * @param array $primes - * @param array $exponents - * @param array $coefficients - * @param string $password optional - * @return string - */ - static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, $primes, $exponents, $coefficients, $password = '') - { - if (count($primes) != 2) { - return false; - } - return "\r\n" . - ' ' . base64_encode($n->toBytes()) . "\r\n" . - ' ' . base64_encode($e->toBytes()) . "\r\n" . - '

' . base64_encode($primes[1]->toBytes()) . "

\r\n" . - ' ' . base64_encode($primes[2]->toBytes()) . "\r\n" . - ' ' . base64_encode($exponents[1]->toBytes()) . "\r\n" . - ' ' . base64_encode($exponents[2]->toBytes()) . "\r\n" . - ' ' . base64_encode($coefficients[2]->toBytes()) . "\r\n" . - ' ' . base64_encode($d->toBytes()) . "\r\n" . - '
'; - } - - /** - * Convert a public key to the appropriate format - * - * @access public - * @param \phpseclib\Math\BigInteger $n - * @param \phpseclib\Math\BigInteger $e - * @return string - */ - static function savePublicKey(BigInteger $n, BigInteger $e) - { - return "\r\n" . - ' ' . base64_encode($n->toBytes()) . "\r\n" . - ' ' . base64_encode($e->toBytes()) . "\r\n" . - ''; - } -} diff --git a/phpseclib/Crypt/Random.php b/phpseclib/Crypt/Random.php index 766eeb4f..9fb1d15b 100644 --- a/phpseclib/Crypt/Random.php +++ b/phpseclib/Crypt/Random.php @@ -24,6 +24,14 @@ namespace phpseclib\Crypt; +use phpseclib\Crypt\AES; +use phpseclib\Crypt\Base; +use phpseclib\Crypt\Blowfish; +use phpseclib\Crypt\DES; +use phpseclib\Crypt\RC4; +use phpseclib\Crypt\TripleDES; +use phpseclib\Crypt\Twofish; + /** * Pure-PHP Random Number Generator * @@ -40,23 +48,56 @@ class Random * microoptimizations because this function has the potential of being called a huge number of times. * eg. for RSA key generation. * - * @param int $length - * @throws \RuntimeException if a symmetric cipher is needed but not loaded - * @return string + * @param Integer $length + * @return String */ - static function string($length) + public static function string($length) { - 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. + if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { + // method 1. prior to PHP 5.3 this would call rand() on windows hence the function_exists('class_alias') call. + // ie. class_alias is a function that was introduced in PHP 5.3 + if (function_exists('mcrypt_create_iv') && function_exists('class_alias')) { + 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 , "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 (function_exists('openssl_random_pseudo_bytes') && version_compare(PHP_VERSION, '5.3.4', '>=')) { + return openssl_random_pseudo_bytes($length); + } + } else { + // method 1. the fastest + if (function_exists('openssl_random_pseudo_bytes')) { + 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 (function_exists('mcrypt_create_iv')) { + return mcrypt_create_iv($length, MCRYPT_DEV_URANDOM); + } } // at this point we have no choice but to use a pure-PHP CSPRNG @@ -94,13 +135,13 @@ class Random session_start(); $v = $seed = $_SESSION['seed'] = pack('H*', sha1( - (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) + serialize($_SERVER) . + serialize($_POST) . + serialize($_GET) . + serialize($_COOKIE) . + serialize($GLOBALS) . + serialize($_SESSION) . + serialize($_OLD_SESSION) )); if (!isset($_SESSION['count'])) { $_SESSION['count'] = 0; @@ -158,7 +199,8 @@ class Random $crypto = new RC4(); break; default: - throw new \RuntimeException(__CLASS__ . ' requires at least one symmetric cipher be loaded'); + user_error(__CLASS__ . ' requires at least one symmetric cipher be loaded'); + return false; } $crypto->setKey($key); @@ -185,36 +227,4 @@ class Random } return substr($result, 0, $length); } - - /** - * Safely serialize variables - * - * If a class has a private __sleep() it'll emit a warning - * - * @param mixed $arr - * @access public - */ - function safe_serialize(&$arr) - { - if (is_object($arr)) { - return ''; - } - if (!is_array($arr)) { - return serialize($arr); - } - // prevent circular array recursion - if (isset($arr['__phpseclib_marker'])) { - return ''; - } - $safearr = array(); - $arr['__phpseclib_marker'] = true; - foreach (array_keys($arr) as $key) { - // do not recurse on the '__phpseclib_marker' key itself, for smaller memory usage - if ($key !== '__phpseclib_marker') { - $safearr[$key] = self::safe_serialize($arr[$key]); - } - } - unset($arr['__phpseclib_marker']); - return serialize($safearr); - } } diff --git a/phpseclib/Crypt/Rijndael.php b/phpseclib/Crypt/Rijndael.php index c98f02e2..90c75d83 100644 --- a/phpseclib/Crypt/Rijndael.php +++ b/phpseclib/Crypt/Rijndael.php @@ -7,11 +7,11 @@ * * PHP version 5 * - * If {@link self::setBlockLength() setBlockLength()} isn't called, it'll be assumed to be 128 bits. If - * {@link self::setKeyLength() setKeyLength()} isn't called, it'll be calculated from - * {@link self::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's + * If {@link \phpseclib\Crypt\Rijndael::setBlockLength() setBlockLength()} isn't called, it'll be assumed to be 128 bits. If + * {@link \phpseclib\Crypt\Rijndael::setKeyLength() setKeyLength()} isn't called, it'll be calculated from + * {@link \phpseclib\Crypt\Rijndael::setKey() setKey()}. ie. if the key is 128-bits, the key length will be 128-bits. If it's * 136-bits it'll be null-padded to 192-bits and 192 bits will be the key length until - * {@link self::setKey() setKey()} is called, again, at which point, it'll be recalculated. + * {@link \phpseclib\Crypt\Rijndael::setKey() setKey()} is called, again, at which point, it'll be recalculated. * * Not all Rijndael implementations may support 160-bits or 224-bits as the block length / key length. mcrypt, for example, * does not. AES, itself, only supports block lengths of 128 and key lengths of 128, 192, and 256. @@ -54,6 +54,8 @@ namespace phpseclib\Crypt; +use phpseclib\Crypt\Base; + /** * Pure-PHP implementation of Rijndael. * @@ -63,18 +65,28 @@ namespace phpseclib\Crypt; */ class Rijndael extends Base { + /** + * The default password key_size used by setPassword() + * + * @see \phpseclib\Crypt\Base::password_key_size + * @see \phpseclib\Crypt\Base::setPassword() + * @var Integer + * @access private + */ + var $password_key_size = 16; + /** * The mcrypt specific name of the cipher * - * Mcrypt is useable for 128/192/256-bit $block_size/$key_length. For 160/224 not. + * Mcrypt is useable for 128/192/256-bit $block_size/$key_size. For 160/224 not. * \phpseclib\Crypt\Rijndael determines automatically whether mcrypt is useable - * or not for the current $block_size/$key_length. + * or not for the current $block_size/$key_size. * In case of, $cipher_name_mcrypt will be set dynamically at run time accordingly. * * @see \phpseclib\Crypt\Base::cipher_name_mcrypt * @see \phpseclib\Crypt\Base::engine - * @see self::isValidEngine() - * @var string + * @see isValidEngine() + * @var String * @access private */ var $cipher_name_mcrypt = 'rijndael-128'; @@ -84,16 +96,25 @@ class Rijndael extends Base * * @see \phpseclib\Crypt\Base::password_default_salt * @see \phpseclib\Crypt\Base::setPassword() - * @var string + * @var String * @access private */ var $password_default_salt = 'phpseclib'; + /** + * Has the key length explicitly been set or should it be derived from the key, itself? + * + * @see setKeyLength() + * @var Boolean + * @access private + */ + var $explicit_key_length = false; + /** * The Key Schedule * - * @see self::_setup() - * @var array + * @see _setup() + * @var Array * @access private */ var $w; @@ -101,8 +122,8 @@ class Rijndael extends Base /** * The Inverse Key Schedule * - * @see self::_setup() - * @var array + * @see _setup() + * @var Array * @access private */ var $dw; @@ -110,8 +131,8 @@ class Rijndael extends Base /** * The Block Length divided by 32 * - * @see self::setBlockLength() - * @var int + * @see setBlockLength() + * @var Integer * @access private * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4. Exists in conjunction with $block_size * because the encryption / decryption / key schedule creation requires this number and not $block_size. We could @@ -121,23 +142,23 @@ class Rijndael extends Base var $Nb = 4; /** - * The Key Length (in bytes) + * The Key Length * - * @see self::setKeyLength() - * @var int + * @see setKeyLength() + * @var Integer * @access private * @internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16. Exists in conjunction with $Nk - * because the encryption / decryption / key schedule creation requires this number and not $key_length. We could - * derive this from $key_length or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu + * because the encryption / decryption / key schedule creation requires this number and not $key_size. We could + * derive this from $key_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu * of that, we'll just precompute it once. */ - var $key_length = 16; + var $key_size = 16; /** * The Key Length divided by 32 * - * @see self::setKeyLength() - * @var int + * @see setKeyLength() + * @var Integer * @access private * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4 */ @@ -146,7 +167,7 @@ class Rijndael extends Base /** * The Number of Rounds * - * @var int + * @var Integer * @access private * @internal The max value is 14, the min value is 10. */ @@ -155,7 +176,7 @@ class Rijndael extends Base /** * Shift offsets * - * @var array + * @var Array * @access private */ var $c; @@ -163,7 +184,7 @@ class Rijndael extends Base /** * Holds the last used key- and block_size information * - * @var array + * @var Array * @access private */ var $kl; @@ -171,23 +192,72 @@ class Rijndael extends Base /** * Default Constructor. * - * @param int $mode + * Determines whether or not the mcrypt extension should be used. + * + * $mode could be: + * + * - \phpseclib\Crypt\Base::MODE_ECB + * + * - \phpseclib\Crypt\Base::MODE_CBC + * + * - \phpseclib\Crypt\Base::MODE_CTR + * + * - \phpseclib\Crypt\Base::MODE_CFB + * + * - \phpseclib\Crypt\Base::MODE_OFB + * + * If not explictly set, \phpseclib\Crypt\Base::MODE_CBC will be used. + * + * @see \phpseclib\Crypt\Base::Crypt_Base() + * @param optional Integer $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. + * + * Keys can be of any length. Rijndael, itself, requires the use of a key that's between 128-bits and 256-bits long and + * whose length is a multiple of 32. If the key is less than 256-bits and the key length isn't set, we round the length + * up to the closest valid key length, padding $key with null bytes. If the key is more than 256-bits, we trim the + * excess bits. + * + * If the key is not explicitly set, it'll be assumed to be all null bytes. + * + * Note: 160/224-bit keys must explicitly set by setKeyLength(), otherwise they will be round/pad up to 192/256 bits. + * + * @see \phpseclib\Crypt\Base:setKey() + * @see setKeyLength() + * @access public + * @param String $key + */ + function setKey($key) + { + if (!$this->explicit_key_length) { + $length = strlen($key); + switch (true) { + case $length <= 16: + $this->key_size = 16; + break; + case $length <= 20: + $this->key_size = 20; + break; + case $length <= 24: + $this->key_size = 24; + break; + case $length <= 28: + $this->key_size = 28; + break; + default: + $this->key_size = 32; + } + } + parent::setKey($key); } /** - * Sets the key length. + * Sets the key length * - * Valid key lengths are 128, 160, 192, 224, and 256. + * 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. * * 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 @@ -201,75 +271,51 @@ class Rijndael extends Base * This results then in slower encryption. * * @access public - * @throws \LengthException if the key length is invalid - * @param int $length + * @param Integer $length */ function setKeyLength($length) { - switch ($length) { - case 128: - case 160: - case 192: - case 224: - case 256: - $this->key_length = $length >> 3; + switch (true) { + case $length == 160: + $this->key_size = 20; + break; + case $length == 224: + $this->key_size = 28; + break; + case $length <= 128: + $this->key_size = 16; + break; + case $length <= 192: + $this->key_size = 24; 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->key_size = 32; } - 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); + $this->explicit_key_length = true; + $this->changed = true; + $this->_setEngine(); } /** * Sets the block length * - * Valid block lengths are 128, 160, 192, 224, and 256. + * 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. * * @access public - * @param int $length + * @param Integer $length */ function setBlockLength($length) { - 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'); + $length >>= 5; + if ($length > 8) { + $length = 8; + } elseif ($length < 4) { + $length = 4; } - - $this->Nb = $length >> 5; - $this->block_size = $length >> 3; + $this->Nb = $length; + $this->block_size = $length << 2; $this->changed = true; $this->_setEngine(); } @@ -279,10 +325,10 @@ class Rijndael extends Base * * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine() * - * @see \phpseclib\Crypt\Base::__construct() - * @param int $engine + * @see \phpseclib\Crypt\Base::Crypt_Base() + * @param Integer $engine * @access public - * @return bool + * @return Boolean */ function isValidEngine($engine) { @@ -291,12 +337,12 @@ class Rijndael extends Base if ($this->block_size != 16) { return false; } - $this->cipher_name_openssl_ecb = 'aes-' . ($this->key_length << 3) . '-ecb'; - $this->cipher_name_openssl = 'aes-' . ($this->key_length << 3) . '-' . $this->_openssl_translate_mode(); + $this->cipher_name_openssl_ecb = 'aes-' . ($this->key_size << 3) . '-ecb'; + $this->cipher_name_openssl = 'aes-' . ($this->key_size << 3) . '-' . $this->_openssl_translate_mode(); break; case self::ENGINE_MCRYPT: $this->cipher_name_mcrypt = 'rijndael-' . ($this->block_size << 3); - if ($this->key_length % 8) { // is it a 160/224-bit key? + if ($this->key_size % 8) { // is it a 160/224-bit key? // mcrypt is not usable for them, only for 128/192/256-bit keys return false; } @@ -305,12 +351,24 @@ class Rijndael extends Base return parent::isValidEngine($engine); } + /** + * Setup the \phpseclib\Crypt\Base::ENGINE_MCRYPT $engine + * + * @see \phpseclib\Crypt\Base::_setupMcrypt() + * @access private + */ + function _setupMcrypt() + { + $this->key = str_pad(substr($this->key, 0, $this->key_size), $this->key_size, "\0"); + parent::_setupMcrypt(); + } + /** * Encrypts a block * * @access private - * @param string $in - * @return string + * @param String $in + * @return String */ function _encryptBlock($in) { @@ -410,8 +468,8 @@ class Rijndael extends Base * Decrypts a block * * @access private - * @param string $in - * @return string + * @param String $in + * @return String */ function _decryptBlock($in) { @@ -515,13 +573,15 @@ class Rijndael extends Base 0x7D000000, 0xFA000000, 0xEF000000, 0xC5000000, 0x91000000 ); - if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->key_length === $this->kl['key_length'] && $this->block_size === $this->kl['block_size']) { + $this->key = str_pad(substr($this->key, 0, $this->key_size), $this->key_size, "\0"); + + if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->key_size === $this->kl['key_size'] && $this->block_size === $this->kl['block_size']) { // already expanded return; } - $this->kl = array('key' => $this->key, 'key_length' => $this->key_length, 'block_size' => $this->block_size); + $this->kl = array('key' => $this->key, 'key_size' => $this->key_size, 'block_size' => $this->block_size); - $this->Nk = $this->key_length >> 2; + $this->Nk = $this->key_size >> 2; // see Rijndael-ammended.pdf#page=44 $this->Nr = max($this->Nk, $this->Nb) + 6; @@ -613,13 +673,13 @@ class Rijndael extends Base * Performs S-Box substitutions * * @access private - * @param int $word + * @param Integer $word */ function _subWord($word) { static $sbox; if (empty($sbox)) { - list(, , , , $sbox) = $this->_getTables(); + list(,,,, $sbox) = $this->_getTables(); } return $sbox[$word & 0x000000FF] | @@ -631,11 +691,11 @@ class Rijndael extends Base /** * Provides the mixColumns and sboxes tables * - * @see self::_encryptBlock() - * @see self::_setupInlineCrypt() - * @see self::_subWord() + * @see Crypt_Rijndael:_encryptBlock() + * @see Crypt_Rijndael:_setupInlineCrypt() + * @see Crypt_Rijndael:_subWord() * @access private - * @return array &$tables + * @return Array &$tables */ function &_getTables() { @@ -720,11 +780,11 @@ class Rijndael extends Base /** * Provides the inverse mixColumns and inverse sboxes tables * - * @see self::_decryptBlock() - * @see self::_setupInlineCrypt() - * @see self::_setupKey() + * @see Crypt_Rijndael:_decryptBlock() + * @see Crypt_Rijndael:_setupInlineCrypt() + * @see Crypt_Rijndael:_setupKey() * @access private - * @return array &$tables + * @return Array &$tables */ function &_getInvTables() { @@ -818,7 +878,7 @@ class Rijndael extends Base // We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function. // (Currently, for Crypt_Rijndael/AES, one generated $lambda_function cost on php5.5@32bit ~80kb unfreeable mem and ~130kb on php5.5@64bit) // After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one. - $gen_hi_opt_code = (bool)(count($lambda_functions) < 10); + $gen_hi_opt_code = (bool)( count($lambda_functions) < 10 ); // Generation of a uniqe hash for our generated code $code_hash = "Crypt_Rijndael, {$this->mode}, {$this->Nr}, {$this->Nb}"; diff --git a/phpseclib/Crypt/TripleDES.php b/phpseclib/Crypt/TripleDES.php index 29c6eb9d..d4caa398 100644 --- a/phpseclib/Crypt/TripleDES.php +++ b/phpseclib/Crypt/TripleDES.php @@ -36,6 +36,9 @@ namespace phpseclib\Crypt; +use phpseclib\Crypt\Base; +use phpseclib\Crypt\DES; + /** * Pure-PHP implementation of Triple DES. * @@ -45,6 +48,7 @@ namespace phpseclib\Crypt; */ class TripleDES extends DES { + /** * Encrypt / decrypt using inner chaining * @@ -56,24 +60,26 @@ class TripleDES extends DES * Encrypt / decrypt using outer chaining * * Outer chaining is used by SSH-2 and when the mode is set to \phpseclib\Crypt\Base::MODE_CBC. - */ + */ const MODE_CBC3 = Base::MODE_CBC; /** - * Key Length (in bytes) + * The default password key_size used by setPassword() * - * @see \phpseclib\Crypt\TripleDES::setKeyLength() - * @var int + * @see \phpseclib\Crypt\DES::password_key_size + * @see \phpseclib\Crypt\Base::password_key_size + * @see \phpseclib\Crypt\Base::setPassword() + * @var Integer * @access private */ - var $key_length = 24; + var $password_key_size = 24; /** * The default salt used by setPassword() * * @see \phpseclib\Crypt\Base::password_default_salt * @see \phpseclib\Crypt\Base::setPassword() - * @var string + * @var String * @access private */ var $password_default_salt = 'phpseclib'; @@ -83,7 +89,7 @@ class TripleDES extends DES * * @see \phpseclib\Crypt\DES::cipher_name_mcrypt * @see \phpseclib\Crypt\Base::cipher_name_mcrypt - * @var string + * @var String * @access private */ var $cipher_name_mcrypt = 'tripledes'; @@ -92,7 +98,7 @@ class TripleDES extends DES * Optimizing value while CFB-encrypting * * @see \phpseclib\Crypt\Base::cfb_init_len - * @var int + * @var Integer * @access private */ var $cfb_init_len = 750; @@ -100,17 +106,17 @@ class TripleDES extends DES /** * max possible size of $key * - * @see self::setKey() + * @see \phpseclib\Crypt\TripleDES::setKey() * @see \phpseclib\Crypt\DES::setKey() - * @var string + * @var String * @access private */ - var $key_length_max = 24; + var $key_size_max = 24; /** * Internal flag whether using self::MODE_3CBC or not * - * @var bool + * @var Boolean * @access private */ var $mode_3cbc; @@ -120,7 +126,7 @@ class TripleDES extends DES * * Used only if $mode_3cbc === true * - * @var array + * @var Array * @access private */ var $des; @@ -128,7 +134,7 @@ class TripleDES extends DES /** * Default Constructor. * - * Determines whether or not the mcrypt or OpenSSL extensions should be used. + * Determines whether or not the mcrypt extension should be used. * * $mode could be: * @@ -142,14 +148,16 @@ class TripleDES extends DES * * - \phpseclib\Crypt\Base::MODE_OFB * - * - \phpseclib\Crypt\TripleDES::MODE_3CB + * - \phpseclib\Crypt\TripleDES::MODE_3CBC + * + * If not explicitly set, \phpseclib\Crypt\Base::MODE_CBC will be used. * * @see \phpseclib\Crypt\DES::__construct() * @see \phpseclib\Crypt\Base::__construct() - * @param int $mode + * @param optional Integer $mode * @access public */ - function __construct($mode) + function __construct($mode = Base::MODE_CBC) { switch ($mode) { // In case of self::MODE_3CBC, we init as CRYPT_DES_MODE_CBC @@ -181,10 +189,10 @@ class TripleDES extends DES * * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine() * - * @see \phpseclib\Crypt\Base::__construct() - * @param int $engine + * @see \phpseclib\Crypt\Base::Crypt_Base() + * @param Integer $engine * @access public - * @return bool + * @return Boolean */ function isValidEngine($engine) { @@ -198,13 +206,14 @@ class TripleDES extends DES } /** - * Sets the initialization vector. + * Sets the initialization vector. (optional) * - * SetIV is not required when \phpseclib\Crypt\Base::MODE_ECB is being used. + * SetIV is not required when \phpseclib\Crypt\Base::MODE_ECB is being used. If not explicitly set, it'll be assumed + * to be all zero's. * * @see \phpseclib\Crypt\Base::setIV() * @access public - * @param string $iv + * @param String $iv */ function setIV($iv) { @@ -216,66 +225,39 @@ class TripleDES extends DES } } - /** - * Sets the key length. - * - * 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) - { - switch ($length) { - case 128: - case 192: - break; - default: - 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); - } - /** * Sets the key. * - * Triple DES can use 128-bit (eg. strlen($key) == 16) or 192-bit (eg. strlen($key) == 24) keys. + * Keys can be of any length. Triple DES, itself, can use 128-bit (eg. strlen($key) == 16) or + * 192-bit (eg. strlen($key) == 24) keys. This function pads and truncates $key as appropriate. * * DES also requires that every eighth bit be a parity bit, however, we'll ignore that. * + * If the key is not explicitly set, it'll be assumed to be all 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 + * @param String $key */ function setKey($key) { - 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'); + $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)); } + parent::setKey($key); - 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) { + // 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) { $this->des[0]->setKey(substr($key, 0, 8)); $this->des[1]->setKey(substr($key, 8, 8)); $this->des[2]->setKey(substr($key, 16, 8)); @@ -287,8 +269,8 @@ class TripleDES extends DES * * @see \phpseclib\Crypt\Base::encrypt() * @access public - * @param string $plaintext - * @return string $cipertext + * @param String $plaintext + * @return String $cipertext */ function encrypt($plaintext) { @@ -314,8 +296,8 @@ class TripleDES extends DES * * @see \phpseclib\Crypt\Base::decrypt() * @access public - * @param string $ciphertext - * @return string $plaintext + * @param String $ciphertext + * @return String $plaintext */ function decrypt($ciphertext) { @@ -369,7 +351,7 @@ class TripleDES extends DES * however, they are also less intuitive and more likely to cause you problems. * * @see \phpseclib\Crypt\Base::enableContinuousBuffer() - * @see self::disableContinuousBuffer() + * @see \phpseclib\Crypt\TripleDES::disableContinuousBuffer() * @access public */ function enableContinuousBuffer() @@ -388,7 +370,7 @@ class TripleDES extends DES * The default behavior. * * @see \phpseclib\Crypt\Base::disableContinuousBuffer() - * @see self::enableContinuousBuffer() + * @see \phpseclib\Crypt\TripleDES::enableContinuousBuffer() * @access public */ function disableContinuousBuffer() @@ -439,11 +421,11 @@ class TripleDES extends DES /** * Sets the internal crypt engine * - * @see \phpseclib\Crypt\Base::__construct() + * @see \phpseclib\Crypt\Base::Crypt_Base() * @see \phpseclib\Crypt\Base::setPreferredEngine() - * @param int $engine + * @param Integer $engine * @access public - * @return int + * @return Integer */ function setPreferredEngine($engine) { diff --git a/phpseclib/Crypt/Twofish.php b/phpseclib/Crypt/Twofish.php index e4d910db..9c32de67 100644 --- a/phpseclib/Crypt/Twofish.php +++ b/phpseclib/Crypt/Twofish.php @@ -37,6 +37,8 @@ namespace phpseclib\Crypt; +use phpseclib\Crypt\Base; + /** * Pure-PHP implementation of Twofish. * @@ -51,7 +53,7 @@ class Twofish extends Base * The mcrypt specific name of the cipher * * @see \phpseclib\Crypt\Base::cipher_name_mcrypt - * @var string + * @var String * @access private */ var $cipher_name_mcrypt = 'twofish'; @@ -60,7 +62,7 @@ class Twofish extends Base * Optimizing value while CFB-encrypting * * @see \phpseclib\Crypt\Base::cfb_init_len - * @var int + * @var Integer * @access private */ var $cfb_init_len = 800; @@ -68,10 +70,10 @@ class Twofish extends Base /** * Q-Table * - * @var array + * @var Array * @access private */ - var $q0 = array( + var $q0 = array ( 0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76, 0x9A, 0x92, 0x80, 0x78, 0xE4, 0xDD, 0xD1, 0x38, 0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C, @@ -109,10 +111,10 @@ class Twofish extends Base /** * Q-Table * - * @var array + * @var Array * @access private */ - var $q1 = array( + var $q1 = array ( 0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8, 0x4A, 0xD3, 0xE6, 0x6B, 0x45, 0x7D, 0xE8, 0x4B, 0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1, @@ -150,10 +152,10 @@ class Twofish extends Base /** * M-Table * - * @var array + * @var Array * @access private */ - var $m0 = array( + var $m0 = array ( 0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B, 0xE2E22BFB, 0x9E9EFAC8, 0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B, 0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B, 0x3C3C57D6, 0x93938A32, 0x8282EED8, 0x525298FD, 0x7B7BD437, 0xBBBB3771, 0x5B5B97F1, 0x474783E1, @@ -191,10 +193,10 @@ class Twofish extends Base /** * M-Table * - * @var array + * @var Array * @access private */ - var $m1 = array( + var $m1 = array ( 0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252, 0xA3658080, 0x76DFE4E4, 0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A, 0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A, 0x0D54E6E6, 0xC6432020, 0x3562CCCC, 0x98BEF2F2, 0x181E1212, 0xF724EBEB, 0xECD7A1A1, 0x6C774141, @@ -232,10 +234,10 @@ class Twofish extends Base /** * M-Table * - * @var array + * @var Array * @access private */ - var $m2 = array( + var $m2 = array ( 0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B, 0xE2FBE22B, 0x9EC89EFA, 0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F, 0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7, 0x3CD63C57, 0x9332938A, 0x82D882EE, 0x52FD5298, 0x7B377BD4, 0xBB71BB37, 0x5BF15B97, 0x47E14783, @@ -273,10 +275,10 @@ class Twofish extends Base /** * M-Table * - * @var array + * @var Array * @access private */ - var $m3 = array( + var $m3 = array ( 0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98, 0x6580A365, 0xDFE476DF, 0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866, 0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836, 0x54E60D54, 0x4320C643, 0x62CC3562, 0xBEF298BE, 0x1E12181E, 0x24EBF724, 0xD7A1ECD7, 0x77416C77, @@ -314,7 +316,7 @@ class Twofish extends Base /** * The Key Schedule Array * - * @var array + * @var Array * @access private */ var $K = array(); @@ -322,7 +324,7 @@ class Twofish extends Base /** * The Key depended S-Table 0 * - * @var array + * @var Array * @access private */ var $S0 = array(); @@ -330,7 +332,7 @@ class Twofish extends Base /** * The Key depended S-Table 1 * - * @var array + * @var Array * @access private */ var $S1 = array(); @@ -338,7 +340,7 @@ class Twofish extends Base /** * The Key depended S-Table 2 * - * @var array + * @var Array * @access private */ var $S2 = array(); @@ -346,7 +348,7 @@ class Twofish extends Base /** * The Key depended S-Table 3 * - * @var array + * @var Array * @access private */ var $S3 = array(); @@ -354,79 +356,40 @@ class Twofish extends Base /** * Holds the last used key * - * @var array + * @var Array * @access private */ var $kl; - /** - * The Key Length (in bytes) - * - * @see Crypt_Twofish::setKeyLength() - * @var int - * @access private - */ - 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. - * - * Valid key lengths are 128, 192 or 256 bits - * - * @access public - * @param int $length - */ - function setKeyLength($length) - { - switch ($length) { - case 128: - case 192: - case 256: - 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::setKeyLength($length); - } - /** * Sets the key. * - * Rijndael supports five different key lengths + * Keys can be of any length. Twofish, itself, requires the use of a key that's 128, 192 or 256-bits long. + * If the key is less than 256-bits we round the length up to the closest valid key length, + * padding $key with null bytes. If the key is more than 256-bits, we trim the excess bits. + * + * If the key is not explicitly set, it'll be assumed a 128 bits key to be all null bytes. * - * @see setKeyLength() * @access public - * @param string $key - * @throws \LengthException if the key length isn't supported + * @see \phpseclib\Crypt\Base::setKey() + * @param String $key */ function setKey($key) { - switch (strlen($key)) { - case 16: - case 24: - case 32: + $keylength = strlen($key); + switch (true) { + case $keylength <= 16: + $key = str_pad($key, 16, "\0"); break; - default: - throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported'); + case $keylength <= 24: + $key = str_pad($key, 24, "\0"); + break; + case $keylength < 32: + $key = str_pad($key, 32, "\0"); + break; + case $keylength > 32: + $key = substr($key, 0, 32); } - parent::setKey($key); } @@ -458,9 +421,9 @@ class Twofish extends Base switch (strlen($this->key)) { case 16: - list($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[1], $le_longs[2]); - list($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[3], $le_longs[4]); - for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) { + list ($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[1], $le_longs[2]); + list ($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[3], $le_longs[4]); + for ($i = 0, $j = 1; $i < 40; $i+= 2,$j+= 2) { $A = $m0[$q0[$q0[$i] ^ $key[ 9]] ^ $key[1]] ^ $m1[$q0[$q1[$i] ^ $key[10]] ^ $key[2]] ^ $m2[$q1[$q0[$i] ^ $key[11]] ^ $key[3]] ^ @@ -481,9 +444,9 @@ class Twofish extends Base } break; case 24: - list($sb, $sa, $s9, $s8) = $this->_mdsrem($le_longs[1], $le_longs[2]); - list($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[3], $le_longs[4]); - list($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[5], $le_longs[6]); + list ($sb, $sa, $s9, $s8) = $this->_mdsrem($le_longs[1], $le_longs[2]); + list ($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[3], $le_longs[4]); + list ($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[5], $le_longs[6]); for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) { $A = $m0[$q0[$q0[$q1[$i] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^ $m1[$q0[$q1[$q1[$i] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^ @@ -505,10 +468,10 @@ class Twofish extends Base } break; default: // 32 - list($sf, $se, $sd, $sc) = $this->_mdsrem($le_longs[1], $le_longs[2]); - list($sb, $sa, $s9, $s8) = $this->_mdsrem($le_longs[3], $le_longs[4]); - list($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[5], $le_longs[6]); - list($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[7], $le_longs[8]); + list ($sf, $se, $sd, $sc) = $this->_mdsrem($le_longs[1], $le_longs[2]); + list ($sb, $sa, $s9, $s8) = $this->_mdsrem($le_longs[3], $le_longs[4]); + list ($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[5], $le_longs[6]); + list ($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[7], $le_longs[8]); for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) { $A = $m0[$q0[$q0[$q1[$q1[$i] ^ $key[25]] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^ $m1[$q0[$q1[$q1[$q0[$i] ^ $key[26]] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^ @@ -541,9 +504,9 @@ class Twofish extends Base * _mdsrem function using by the twofish cipher algorithm * * @access private - * @param string $A - * @param string $B - * @return array + * @param String $A + * @param String $B + * @return Array */ function _mdsrem($A, $B) { @@ -589,8 +552,8 @@ class Twofish extends Base * Encrypts a block * * @access private - * @param string $in - * @return string + * @param String $in + * @return String */ function _encryptBlock($in) { @@ -645,8 +608,8 @@ class Twofish extends Base * Decrypts a block * * @access private - * @param string $in - * @return string + * @param String $in + * @return String */ function _decryptBlock($in) { @@ -709,7 +672,7 @@ class Twofish extends Base // Max. 10 Ultra-Hi-optimized inline-crypt functions. After that, we'll (still) create very fast code, but not the ultimate fast one. // (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); + $gen_hi_opt_code = (bool)( count($lambda_functions) < 10 ); // Generation of a uniqe hash for our generated code $code_hash = "Crypt_Twofish, {$this->mode}"; diff --git a/phpseclib/Exception/BadConfigurationException.php b/phpseclib/Exception/BadConfigurationException.php deleted file mode 100644 index 096148a0..00000000 --- a/phpseclib/Exception/BadConfigurationException.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Exception; - -/** - * BadConfigurationException - * - * @package BadConfigurationException - * @author Jim Wigginton - */ -class BadConfigurationException extends \RuntimeException -{ -} diff --git a/phpseclib/Exception/FileNotFoundException.php b/phpseclib/Exception/FileNotFoundException.php deleted file mode 100644 index 984edfcc..00000000 --- a/phpseclib/Exception/FileNotFoundException.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Exception; - -/** - * FileNotFoundException - * - * @package FileNotFoundException - * @author Jim Wigginton - */ -class FileNotFoundException extends \RuntimeException -{ -} diff --git a/phpseclib/Exception/NoSupportedAlgorithmsException.php b/phpseclib/Exception/NoSupportedAlgorithmsException.php deleted file mode 100644 index bca9a753..00000000 --- a/phpseclib/Exception/NoSupportedAlgorithmsException.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Exception; - -/** - * NoSupportedAlgorithmsException - * - * @package NoSupportedAlgorithmsException - * @author Jim Wigginton - */ -class NoSupportedAlgorithmsException extends \RuntimeException -{ -} diff --git a/phpseclib/Exception/UnsupportedAlgorithmException.php b/phpseclib/Exception/UnsupportedAlgorithmException.php deleted file mode 100644 index 47cc41d4..00000000 --- a/phpseclib/Exception/UnsupportedAlgorithmException.php +++ /dev/null @@ -1,26 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - * @link http://phpseclib.sourceforge.net - */ - -namespace phpseclib\Exception; - -/** - * UnsupportedAlgorithmException - * - * @package UnsupportedAlgorithmException - * @author Jim Wigginton - */ -class UnsupportedAlgorithmException extends \RuntimeException -{ -} diff --git a/phpseclib/File/ANSI.php b/phpseclib/File/ANSI.php index 1f3eecb3..1daf787a 100644 --- a/phpseclib/File/ANSI.php +++ b/phpseclib/File/ANSI.php @@ -32,7 +32,7 @@ class ANSI /** * Max Width * - * @var int + * @var Integer * @access private */ var $max_x; @@ -40,7 +40,7 @@ class ANSI /** * Max Height * - * @var int + * @var Integer * @access private */ var $max_y; @@ -48,7 +48,7 @@ class ANSI /** * Max History * - * @var int + * @var Integer * @access private */ var $max_history; @@ -56,7 +56,7 @@ class ANSI /** * History * - * @var array + * @var Array * @access private */ var $history; @@ -64,7 +64,7 @@ class ANSI /** * History Attributes * - * @var array + * @var Array * @access private */ var $history_attrs; @@ -72,7 +72,7 @@ class ANSI /** * Current Column * - * @var int + * @var Integer * @access private */ var $x; @@ -80,7 +80,7 @@ class ANSI /** * Current Row * - * @var int + * @var Integer * @access private */ var $y; @@ -88,7 +88,7 @@ class ANSI /** * Old Column * - * @var int + * @var Integer * @access private */ var $old_x; @@ -96,7 +96,7 @@ class ANSI /** * Old Row * - * @var int + * @var Integer * @access private */ var $old_y; @@ -104,7 +104,7 @@ class ANSI /** * An empty attribute cell * - * @var object + * @var Object * @access private */ var $base_attr_cell; @@ -112,7 +112,7 @@ class ANSI /** * The current attribute cell * - * @var object + * @var Object * @access private */ var $attr_cell; @@ -120,7 +120,7 @@ class ANSI /** * An empty attribute row * - * @var array + * @var Array * @access private */ var $attr_row; @@ -128,7 +128,7 @@ class ANSI /** * The current screen text * - * @var array + * @var Array * @access private */ var $screen; @@ -136,7 +136,7 @@ class ANSI /** * The current screen attributes * - * @var array + * @var Array * @access private */ var $attrs; @@ -144,7 +144,7 @@ class ANSI /** * Current ANSI code * - * @var string + * @var String * @access private */ var $ansi; @@ -152,7 +152,7 @@ class ANSI /** * Tokenization * - * @var array + * @var Array * @access private */ var $tokenization; @@ -184,8 +184,8 @@ class ANSI * * Resets the screen as well * - * @param int $x - * @param int $y + * @param Integer $x + * @param Integer $y * @access public */ function setDimensions($x, $y) @@ -203,8 +203,8 @@ class ANSI /** * Set the number of lines that should be logged past the terminal height * - * @param int $x - * @param int $y + * @param Integer $x + * @param Integer $y * @access public */ function setHistory($history) @@ -215,7 +215,7 @@ class ANSI /** * Load a string * - * @param string $source + * @param String $source * @access public */ function loadString($source) @@ -227,7 +227,7 @@ class ANSI /** * Appdend a string * - * @param string $source + * @param String $source * @access public */ function appendString($source) @@ -458,7 +458,7 @@ class ANSI * Returns the current coordinate without preformating * * @access private - * @return string + * @return String */ function _processCoordinate($last_attr, $cur_attr, $char) { @@ -515,7 +515,7 @@ class ANSI * Returns the current screen without preformating * * @access private - * @return string + * @return String */ function _getScreen() { @@ -539,7 +539,7 @@ class ANSI * Returns the current screen * * @access public - * @return string + * @return String */ function getScreen() { @@ -550,7 +550,7 @@ class ANSI * Returns the current screen and the x previous lines * * @access public - * @return string + * @return String */ function getHistory() { diff --git a/phpseclib/File/ASN1.php b/phpseclib/File/ASN1.php index 180b0e67..717f4f8d 100644 --- a/phpseclib/File/ASN1.php +++ b/phpseclib/File/ASN1.php @@ -104,7 +104,7 @@ class ASN1 /** * ASN.1 object identifier * - * @var array + * @var Array * @access private * @link http://en.wikipedia.org/wiki/Object_identifier */ @@ -113,7 +113,7 @@ class ASN1 /** * Default date format * - * @var string + * @var String * @access private * @link http://php.net/class.datetime */ @@ -122,10 +122,10 @@ class ASN1 /** * Default date format * - * @var array + * @var Array * @access private - * @see self::setTimeFormat() - * @see self::asn1map() + * @see \phpseclib\File\ASN1::setTimeFormat() + * @see \phpseclib\File\ASN1::asn1map() * @link http://php.net/class.datetime */ var $encoded; @@ -135,9 +135,9 @@ class ASN1 * * If the mapping type is self::TYPE_ANY what do we actually encode it as? * - * @var array + * @var Array * @access private - * @see self::_encode_der() + * @see \phpseclib\File\ASN1::_encode_der() */ var $filters; @@ -148,7 +148,7 @@ class ASN1 * Unambiguous types get the direct mapping (int/real/bool). * Others are mapped as a choice, with an extra indexing level. * - * @var array + * @var Array * @access public */ var $ANYmap = array( @@ -182,7 +182,7 @@ class ASN1 * Non-convertable types are absent from this table. * size == 0 indicates variable length encoding. * - * @var array + * @var Array * @access public */ var $stringTypeSize = array( @@ -200,8 +200,8 @@ class ASN1 * * Serves a similar purpose to openssl's asn1parse * - * @param string $encoded - * @return array + * @param String $encoded + * @return Array * @access public */ function decodeBER($encoded) @@ -222,9 +222,9 @@ class ASN1 * $encoded is passed by reference for the recursive calls done for self::TYPE_BIT_STRING and * self::TYPE_OCTET_STRING. In those cases, the indefinite length is used. * - * @param string $encoded - * @param int $start - * @return array + * @param String $encoded + * @param Integer $start + * @return Array * @access private */ function _decode_ber($encoded, $start = 0) @@ -482,10 +482,10 @@ class ASN1 * * "Special" mappings may be applied on a per tag-name basis via $special. * - * @param array $decoded - * @param array $mapping - * @param array $special - * @return array + * @param Array $decoded + * @param Array $mapping + * @param Array $special + * @return Array * @access public */ function asn1map($decoded, $mapping, $special = array()) @@ -616,7 +616,7 @@ class ASN1 } // Fail mapping if all input items have not been consumed. - return $i < $n ? null: $map; + return $i < $n? null: $map; // the main diff between sets and sequences is the encapsulation of the foreach in another for loop case self::TYPE_SET: @@ -774,10 +774,10 @@ class ASN1 * * "Special" mappings can be applied via $special. * - * @param string $source - * @param string $mapping - * @param int $idx - * @return string + * @param String $source + * @param String $mapping + * @param Integer $idx + * @return String * @access public */ function encodeDER($source, $mapping, $special = array()) @@ -789,11 +789,10 @@ class ASN1 /** * ASN.1 Encode (Helper function) * - * @param string $source - * @param string $mapping - * @param int $idx - * @return string - * @throws \RuntimeException if the input has an error in it + * @param String $source + * @param String $mapping + * @param Integer $idx + * @return String * @access private */ function _encode_der($source, $mapping, $idx = null, $special = array()) @@ -986,7 +985,7 @@ class ASN1 case self::TYPE_OBJECT_IDENTIFIER: $oid = preg_match('#(?:\d+\.)+#', $source) ? $source : array_search($source, $this->oids); if ($oid === false) { - throw new \RuntimeException('Invalid OID'); + user_error('Invalid OID'); return false; } $value = ''; @@ -1039,7 +1038,7 @@ class ASN1 $filters = $filters[$part]; } if ($filters === false) { - throw new \RuntimeException('No filters defined for ' . implode('/', $loc)); + user_error('No filters defined for ' . implode('/', $loc)); return false; } return $this->_encode_der($source, $filters + $mapping, null, $special); @@ -1063,7 +1062,7 @@ class ASN1 $value = $source ? "\xFF" : "\x00"; break; default: - throw new \RuntimeException('Mapping provides no type definition for ' . implode('/', $this->location)); + user_error('Mapping provides no type definition for ' . implode('/', $this->location)); return false; } @@ -1090,8 +1089,8 @@ class ASN1 * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information. * * @access private - * @param int $length - * @return string + * @param Integer $length + * @return String */ function _encodeLength($length) { @@ -1109,9 +1108,9 @@ class ASN1 * Called by _decode_ber() and in the case of implicit tags asn1map(). * * @access private - * @param string $content - * @param int $tag - * @return string + * @param String $content + * @param Integer $tag + * @return String */ function _decodeTime($content, $tag) { @@ -1158,7 +1157,7 @@ class ASN1 * Sets the time / date format for asn1map(). * * @access public - * @param string $format + * @param String $format */ function setTimeFormat($format) { @@ -1171,7 +1170,7 @@ class ASN1 * Load the relevant OIDs for a particular ASN.1 semantic mapping. * * @access public - * @param array $oids + * @param Array $oids */ function loadOIDs($oids) { @@ -1184,7 +1183,7 @@ class ASN1 * See \phpseclib\File\X509, etc, for an example. * * @access public - * @param array $filters + * @param Array $filters */ function loadFilters($filters) { @@ -1196,9 +1195,9 @@ class ASN1 * * Inspired by array_shift * - * @param string $string - * @param int $index - * @return string + * @param String $string + * @param optional Integer $index + * @return String * @access private */ function _string_shift(&$string, $index = 1) @@ -1214,10 +1213,10 @@ class ASN1 * This is a lazy conversion, dealing only with character size. * No real conversion table is used. * - * @param string $in - * @param int $from - * @param int $to - * @return string + * @param String $in + * @param optional Integer $from + * @param optional Integer $to + * @return String * @access public */ function convert($in, $from = self::TYPE_UTF8_STRING, $to = self::TYPE_UTF8_STRING) diff --git a/phpseclib/File/ASN1/Element.php b/phpseclib/File/ASN1/Element.php index 68246e2b..d0da53bd 100644 --- a/phpseclib/File/ASN1/Element.php +++ b/phpseclib/File/ASN1/Element.php @@ -28,7 +28,7 @@ class Element /** * Raw element value * - * @var string + * @var String * @access private */ var $element; @@ -36,7 +36,7 @@ class Element /** * Constructor * - * @param string $encoded + * @param String $encoded * @return \phpseclib\File\ASN1\Element * @access public */ diff --git a/phpseclib/File/X509.php b/phpseclib/File/X509.php index 9022ae7c..cfdfbe2e 100644 --- a/phpseclib/File/X509.php +++ b/phpseclib/File/X509.php @@ -27,9 +27,9 @@ namespace phpseclib\File; use phpseclib\Crypt\Hash; -use phpseclib\Crypt\Random; use phpseclib\Crypt\RSA; -use phpseclib\Exception\UnsupportedAlgorithmException; +use phpseclib\Crypt\Random; +use phpseclib\File\ASN1; use phpseclib\File\ASN1\Element; use phpseclib\Math\BigInteger; @@ -57,27 +57,27 @@ class X509 */ /** * Return internal array representation - */ + */ const DN_ARRAY = 0; /** * Return string - */ + */ const DN_STRING = 1; /** * Return ASN.1 name string - */ + */ const DN_ASN1 = 2; /** * Return OpenSSL compatible array - */ + */ const DN_OPENSSL = 3; /** * Return canonical ASN.1 RDNs string - */ + */ const DN_CANON = 4; /** * Return name hash for file indexing - */ + */ const DN_HASH = 5; /**#@-*/ @@ -91,30 +91,24 @@ class X509 * Save as PEM * * ie. a base64-encoded PEM with a header and a footer - */ + */ const FORMAT_PEM = 0; /** * Save as DER - */ + */ const FORMAT_DER = 1; /** * Save as a SPKAC * * Only works on CSRs. Not currently supported. - */ + */ const FORMAT_SPKAC = 2; - /** - * Auto-detect the format - * - * Used only by the load*() functions - */ - const FORMAT_AUTO_DETECT = 3; /**#@-*/ /** * Attribute value disposition. * If disposition is >= 0, this is the index of the target value. - */ + */ const ATTR_ALL = -1; // All attribute values (array). const ATTR_APPEND = -2; // Add a value. const ATTR_REPLACE = -3; // Clear first, then add a value. @@ -122,7 +116,7 @@ class X509 /** * ASN.1 syntax for X.509 certificates * - * @var array + * @var Array * @access private */ var $Certificate; @@ -171,7 +165,7 @@ class X509 /** * ASN.1 syntax for Certificate Signing Requests (RFC2986) * - * @var array + * @var Array * @access private */ var $CertificationRequest; @@ -179,7 +173,7 @@ class X509 /** * ASN.1 syntax for Certificate Revocation Lists (RFC5280) * - * @var array + * @var Array * @access private */ var $CertificateList; @@ -187,7 +181,7 @@ class X509 /** * Distinguished Name * - * @var array + * @var Array * @access private */ var $dn; @@ -195,7 +189,7 @@ class X509 /** * Public key * - * @var string + * @var String * @access private */ var $publicKey; @@ -203,7 +197,7 @@ class X509 /** * Private key * - * @var string + * @var String * @access private */ var $privateKey; @@ -211,7 +205,7 @@ class X509 /** * Object identifiers for X.509 certificates * - * @var array + * @var Array * @access private * @link http://en.wikipedia.org/wiki/Object_identifier */ @@ -220,7 +214,7 @@ class X509 /** * The certificate authorities * - * @var array + * @var Array * @access private */ var $CAs; @@ -228,7 +222,7 @@ class X509 /** * The currently loaded certificate * - * @var array + * @var Array * @access private */ var $currentCert; @@ -239,7 +233,7 @@ class X509 * 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 + * @var String * @access private */ var $signatureSubject; @@ -247,7 +241,7 @@ class X509 /** * Certificate Start Date * - * @var string + * @var String * @access private */ var $startDate; @@ -255,7 +249,7 @@ class X509 /** * Certificate End Date * - * @var string + * @var String * @access private */ var $endDate; @@ -263,7 +257,7 @@ class X509 /** * Serial Number * - * @var string + * @var String * @access private */ var $serialNumber; @@ -274,7 +268,7 @@ class X509 * See {@link http://tools.ietf.org/html/rfc5280#section-4.2.1.1 RFC5280#section-4.2.1.1} and * {@link http://tools.ietf.org/html/rfc5280#section-4.2.1.2 RFC5280#section-4.2.1.2}. * - * @var string + * @var String * @access private */ var $currentKeyIdentifier; @@ -282,7 +276,7 @@ class X509 /** * CA Flag * - * @var bool + * @var Boolean * @access private */ var $caFlag = false; @@ -290,7 +284,7 @@ class X509 /** * SPKAC Challenge * - * @var string + * @var String * @access private */ var $challenge; @@ -1408,12 +1402,11 @@ class X509 * * Returns an associative array describing the X.509 cert or a false if the cert failed to load * - * @param string $cert - * @param int $mode + * @param String $cert * @access public - * @return mixed + * @return Mixed */ - function loadX509($cert, $mode = self::FORMAT_AUTO_DETECT) + function loadX509($cert) { if (is_array($cert) && isset($cert['tbsCertificate'])) { unset($this->currentCert); @@ -1434,13 +1427,7 @@ class X509 $asn1 = new ASN1(); - if ($mode != self::FORMAT_DER) { - $newcert = $this->_extractBER($cert); - if ($mode == self::FORMAT_PEM && $cert == $newcert) { - return false; - } - $cert = $newcert; - } + $cert = $this->_extractBER($cert); if ($cert === false) { $this->currentCert = false; @@ -1477,10 +1464,10 @@ class X509 /** * Save X.509 certificate * - * @param array $cert - * @param int $format optional + * @param Array $cert + * @param Integer $format optional * @access public - * @return string + * @return String */ function saveX509($cert, $format = self::FORMAT_PEM) { @@ -1553,9 +1540,9 @@ class X509 * Map extension values from octet string to extension-specific internal * format. * - * @param array ref $root - * @param string $path - * @param object $asn1 + * @param Array ref $root + * @param String $path + * @param Object $asn1 * @access private */ function _mapInExtensions(&$root, $path, $asn1) @@ -1603,9 +1590,9 @@ class X509 * Map extension values from extension-specific internal format to * octet string. * - * @param array ref $root - * @param string $path - * @param object $asn1 + * @param Array ref $root + * @param String $path + * @param Object $asn1 * @access private */ function _mapOutExtensions(&$root, $path, $asn1) @@ -1654,7 +1641,7 @@ 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 { @@ -1669,9 +1656,9 @@ class X509 * Map attribute values from ANY type to attribute-specific internal * format. * - * @param array ref $root - * @param string $path - * @param object $asn1 + * @param Array ref $root + * @param String $path + * @param Object $asn1 * @access private */ function _mapInAttributes(&$root, $path, $asn1) @@ -1710,9 +1697,9 @@ class X509 * Map attribute values from attribute-specific internal format to * ANY type. * - * @param array ref $root - * @param string $path - * @param object $asn1 + * @param Array ref $root + * @param String $path + * @param Object $asn1 * @access private */ function _mapOutAttributes(&$root, $path, $asn1) @@ -1727,7 +1714,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']; @@ -1752,9 +1739,9 @@ class X509 /** * Associate an extension ID to an extension mapping * - * @param string $extnId + * @param String $extnId * @access private - * @return mixed + * @return Mixed */ function _getMapping($extnId) { @@ -1848,9 +1835,9 @@ class X509 /** * Load an X.509 certificate as a certificate authority * - * @param string $cert + * @param String $cert * @access public - * @return bool + * @return Boolean */ function loadCA($cert) { @@ -1915,9 +1902,9 @@ class X509 * component or component fragment. E.g., *.a.com matches foo.a.com but * not bar.foo.a.com. f*.com matches foo.com but not bar.com. * - * @param string $url + * @param String $url * @access public - * @return bool + * @return Boolean */ function validateURL($url) { @@ -1973,7 +1960,7 @@ class X509 * * If $date isn't defined it is assumed to be the current date. * - * @param int $date optional + * @param Integer $date optional * @access public */ function validateDate($date = null) @@ -2012,9 +1999,9 @@ class X509 * * The behavior of this function is inspired by {@link http://php.net/openssl-verify openssl_verify}. * - * @param bool $caonly optional + * @param Boolean $caonly optional * @access public - * @return mixed + * @return Mixed */ function validateSignature($caonly = true) { @@ -2120,24 +2107,22 @@ class X509 /** * Validates a signature * - * Returns true if the signature is verified and false if it is not correct. - * If the algorithms are unsupposed an exception is thrown. + * Returns true if the signature is verified, false if it is not correct or null on error * - * @param string $publicKeyAlgorithm - * @param string $publicKey - * @param string $signatureAlgorithm - * @param string $signature - * @param string $signatureSubject + * @param String $publicKeyAlgorithm + * @param String $publicKey + * @param String $signatureAlgorithm + * @param String $signature + * @param String $signatureSubject * @access private - * @throws \phpseclib\Exception\UnsupportedAlgorithmException if the algorithm is unsupported - * @return bool + * @return Integer */ function _validateSignature($publicKeyAlgorithm, $publicKey, $signatureAlgorithm, $signature, $signatureSubject) { switch ($publicKeyAlgorithm) { case 'rsaEncryption': $rsa = new RSA(); - $rsa->load($publicKey); + $rsa->loadKey($publicKey); switch ($signatureAlgorithm) { case 'md2WithRSAEncryption': @@ -2148,16 +2133,17 @@ class X509 case 'sha384WithRSAEncryption': case 'sha512WithRSAEncryption': $rsa->setHash(preg_replace('#WithRSAEncryption$#', '', $signatureAlgorithm)); - if (!@$rsa->verify($signatureSubject, $signature, RSA::PADDING_PKCS1)) { + $rsa->setSignatureMode(RSA::SIGNATURE_PKCS1); + if (!@$rsa->verify($signatureSubject, $signature)) { return false; } break; default: - throw new UnsupportedAlgorithmException('Signature algorithm unsupported'); + return null; } break; default: - throw new UnsupportedAlgorithmException('Public key algorithm unsupported'); + return null; } return true; @@ -2168,10 +2154,10 @@ class X509 * * Reformats a public key to a format supported by phpseclib (if applicable) * - * @param string $algorithm - * @param string $key + * @param String $algorithm + * @param String $key * @access private - * @return string + * @return String */ function _reformatKey($algorithm, $key) { @@ -2194,13 +2180,15 @@ class X509 * * Takes in a base64 encoded "blob" and returns a human readable IP address * - * @param string $ip + * @param String $ip * @access private - * @return string + * @return String */ function _decodeIP($ip) { - return inet_ntop(base64_decode($ip)); + $ip = base64_decode($ip); + list(, $ip) = unpack('N', $ip); + return long2ip($ip); } /** @@ -2208,21 +2196,21 @@ class X509 * * Takes a human readable IP address into a base64-encoded "blob" * - * @param string $ip + * @param String $ip * @access private - * @return string + * @return String */ function _encodeIP($ip) { - return base64_encode(inet_pton($ip)); + return base64_encode(pack('N', ip2long($ip))); } /** * "Normalizes" a Distinguished Name property * - * @param string $propName + * @param String $propName * @access private - * @return mixed + * @return Mixed */ function _translateDNProp($propName) { @@ -2309,11 +2297,11 @@ class X509 /** * Set a Distinguished Name property * - * @param string $propName - * @param mixed $propValue - * @param string $type optional + * @param String $propName + * @param Mixed $propValue + * @param String $type optional * @access public - * @return bool + * @return Boolean */ function setDNProp($propName, $propValue, $type = 'utf8String') { @@ -2343,7 +2331,7 @@ class X509 /** * Remove Distinguished Name properties * - * @param string $propName + * @param String $propName * @access public */ function removeDNProp($propName) @@ -2370,10 +2358,10 @@ class X509 /** * Get Distinguished Name properties * - * @param string $propName - * @param array $dn optional - * @param bool $withType optional - * @return mixed + * @param String $propName + * @param Array $dn optional + * @param Boolean $withType optional + * @return Mixed * @access public */ function getDNProp($propName, $dn = null, $withType = false) @@ -2421,11 +2409,11 @@ class X509 /** * Set a Distinguished Name * - * @param mixed $dn - * @param bool $merge optional - * @param string $type optional + * @param Mixed $dn + * @param Boolean $merge optional + * @param String $type optional * @access public - * @return bool + * @return Boolean */ function setDN($dn, $merge = false, $type = 'utf8String') { @@ -2464,10 +2452,10 @@ class X509 /** * Get the Distinguished Name for a certificates subject * - * @param mixed $format optional - * @param array $dn optional + * @param Mixed $format optional + * @param Array $dn optional * @access public - * @return bool + * @return Boolean */ function getDN($format = self::DN_ARRAY, $dn = null) { @@ -2607,9 +2595,9 @@ class X509 /** * Get the Distinguished Name for a certificate/crl issuer * - * @param int $format optional + * @param Integer $format optional * @access public - * @return mixed + * @return Mixed */ function getIssuerDN($format = self::DN_ARRAY) { @@ -2629,9 +2617,9 @@ class X509 * Get the Distinguished Name for a certificate/csr subject * Alias of getDN() * - * @param int $format optional + * @param Integer $format optional * @access public - * @return mixed + * @return Mixed */ function getSubjectDN($format = self::DN_ARRAY) { @@ -2652,10 +2640,10 @@ class X509 /** * Get an individual Distinguished Name property for a certificate/crl issuer * - * @param string $propName - * @param bool $withType optional + * @param String $propName + * @param Boolean $withType optional * @access public - * @return mixed + * @return Mixed */ function getIssuerDNProp($propName, $withType = false) { @@ -2674,10 +2662,10 @@ class X509 /** * Get an individual Distinguished Name property for a certificate/csr subject * - * @param string $propName - * @param bool $withType optional + * @param String $propName + * @param Boolean $withType optional * @access public - * @return mixed + * @return Mixed */ function getSubjectDNProp($propName, $withType = false) { @@ -2699,7 +2687,7 @@ class X509 * Get the certificate chain for the current cert * * @access public - * @return mixed + * @return Mixed */ function getChain() { @@ -2745,9 +2733,9 @@ class X509 * * Key needs to be a \phpseclib\Crypt\RSA object * - * @param object $key + * @param Object $key * @access public - * @return bool + * @return Boolean */ function setPublicKey($key) { @@ -2760,7 +2748,7 @@ class X509 * * Key needs to be a \phpseclib\Crypt\RSA object * - * @param object $key + * @param Object $key * @access public */ function setPrivateKey($key) @@ -2773,7 +2761,7 @@ class X509 * * Used for SPKAC CSR's * - * @param string $challenge + * @param String $challenge * @access public */ function setChallenge($challenge) @@ -2787,7 +2775,7 @@ class X509 * Returns a \phpseclib\Crypt\RSA object or a false. * * @access public - * @return mixed + * @return Mixed */ function getPublicKey() { @@ -2812,7 +2800,7 @@ class X509 switch ($keyinfo['algorithm']['algorithm']) { case 'rsaEncryption': $publicKey = new RSA(); - $publicKey->load($key); + $publicKey->loadKey($key); $publicKey->setPublicKey(); break; default: @@ -2825,11 +2813,11 @@ class X509 /** * Load a Certificate Signing Request * - * @param string $csr + * @param String $csr * @access public - * @return mixed + * @return Mixed */ - function loadCSR($csr, $mode = self::FORMAT_AUTO_DETECT) + function loadCSR($csr) { if (is_array($csr) && isset($csr['certificationRequestInfo'])) { unset($this->currentCert); @@ -2848,13 +2836,7 @@ class X509 $asn1 = new ASN1(); - if ($mode != self::FORMAT_DER) { - $newcsr = $this->_extractBER($csr); - if ($mode == self::FORMAT_PEM && $csr == $newcsr) { - return false; - } - $csr = $newcsr; - } + $csr = $this->_extractBER($csr); $orig = $csr; if ($csr === false) { @@ -2888,7 +2870,7 @@ class X509 switch ($algorithm) { case 'rsaEncryption': $this->publicKey = new RSA(); - $this->publicKey->load($key); + $this->publicKey->loadKey($key); $this->publicKey->setPublicKey(); break; default: @@ -2904,10 +2886,10 @@ class X509 /** * Save CSR request * - * @param array $csr - * @param int $format optional + * @param Array $csr + * @param Integer $format optional * @access public - * @return string + * @return String */ function saveCSR($csr, $format = self::FORMAT_PEM) { @@ -2956,9 +2938,9 @@ class X509 * * https://developer.mozilla.org/en-US/docs/HTML/Element/keygen * - * @param string $csr + * @param String $csr * @access public - * @return mixed + * @return Mixed */ function loadSPKAC($spkac) { @@ -3011,7 +2993,7 @@ class X509 switch ($algorithm) { case 'rsaEncryption': $this->publicKey = new RSA(); - $this->publicKey->load($key); + $this->publicKey->loadKey($key); $this->publicKey->setPublicKey(); break; default: @@ -3027,10 +3009,10 @@ class X509 /** * Save a SPKAC CSR request * - * @param array $csr - * @param int $format optional + * @param Array $csr + * @param Integer $format optional * @access public - * @return string + * @return String */ function saveSPKAC($spkac, $format = self::FORMAT_PEM) { @@ -3070,11 +3052,11 @@ class X509 /** * Load a Certificate Revocation List * - * @param string $crl + * @param String $crl * @access public - * @return mixed + * @return Mixed */ - function loadCRL($crl, $mode = self::FORMAT_AUTO_DETECT) + function loadCRL($crl) { if (is_array($crl) && isset($crl['tbsCertList'])) { $this->currentCert = $crl; @@ -3084,13 +3066,7 @@ class X509 $asn1 = new ASN1(); - if ($mode != self::FORMAT_DER) { - $newcrl = $this->_extractBER($crl); - if ($mode == self::FORMAT_PEM && $crl == $newcrl) { - return false; - } - $crl = $newcrl; - } + $crl = $this->_extractBER($crl); $orig = $crl; if ($crl === false) { @@ -3131,10 +3107,10 @@ class X509 /** * Save Certificate Revocation List. * - * @param array $crl - * @param int $format optional + * @param Array $crl + * @param Integer $format optional * @access public - * @return string + * @return String */ function saveCRL($crl, $format = self::FORMAT_PEM) { @@ -3193,9 +3169,9 @@ class X509 * - 5.1.2.6 Revoked Certificates * by choosing utcTime iff year of date given is before 2050 and generalTime else. * - * @param string $date in format date('D, d M Y H:i:s O') + * @param String $date in format date('D, d M Y H:i:s O') * @access private - * @return array + * @return Array */ function _timeField($date) { @@ -3216,9 +3192,9 @@ class X509 * * @param \phpseclib\File\X509 $issuer * @param \phpseclib\File\X509 $subject - * @param string $signatureAlgorithm optional + * @param String $signatureAlgorithm optional * @access public - * @return mixed + * @return Mixed */ function sign($issuer, $subject, $signatureAlgorithm = 'sha1WithRSAEncryption') { @@ -3395,7 +3371,7 @@ class X509 * Sign a CSR * * @access public - * @return mixed + * @return Mixed */ function signCSR($signatureAlgorithm = 'sha1WithRSAEncryption') { @@ -3406,7 +3382,7 @@ class X509 $origPublicKey = $this->publicKey; $class = get_class($this->privateKey); $this->publicKey = new $class(); - $this->publicKey->load($this->privateKey->getPublicKey()); + $this->publicKey->loadKey($this->privateKey->getPublicKey()); $this->publicKey->setPublicKey(); if (!($publicKey = $this->_formatSubjectPublicKey())) { return false; @@ -3453,7 +3429,7 @@ class X509 * Sign a SPKAC * * @access public - * @return mixed + * @return Mixed */ function signSPKAC($signatureAlgorithm = 'sha1WithRSAEncryption') { @@ -3464,7 +3440,7 @@ class X509 $origPublicKey = $this->publicKey; $class = get_class($this->privateKey); $this->publicKey = new $class(); - $this->publicKey->load($this->privateKey->getPublicKey()); + $this->publicKey->loadKey($this->privateKey->getPublicKey()); $this->publicKey->setPublicKey(); $publicKey = $this->_formatSubjectPublicKey(); if (!$publicKey) { @@ -3521,9 +3497,9 @@ class X509 * * @param \phpseclib\File\X509 $issuer * @param \phpseclib\File\X509 $crl - * @param string $signatureAlgorithm optional + * @param String $signatureAlgorithm optional * @access public - * @return mixed + * @return Mixed */ function signCRL($issuer, $crl, $signatureAlgorithm = 'sha1WithRSAEncryption') { @@ -3648,12 +3624,11 @@ class X509 /** * X.509 certificate signing helper function. * - * @param object $key + * @param Object $key * @param \phpseclib\File\X509 $subject - * @param string $signatureAlgorithm + * @param String $signatureAlgorithm * @access public - * @throws \phpseclib\Exception\UnsupportedAlgorithmException if the algorithm is unsupported - * @return mixed + * @return Mixed */ function _sign($key, $signatureAlgorithm) { @@ -3667,21 +3642,20 @@ 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, RSA::PADDING_PKCS1)); + $this->currentCert['signature'] = base64_encode("\0" . $key->sign($this->signatureSubject)); return $this->currentCert; - default: - throw new UnsupportedAlgorithmException('Signature algorithm unsupported'); } } - throw new UnsupportedAlgorithmException('Unsupported public key algorithm'); + return false; } /** * Set certificate start date * - * @param string $date + * @param String $date * @access public */ function setStartDate($date) @@ -3692,7 +3666,7 @@ class X509 /** * Set certificate end date * - * @param string $date + * @param String $date * @access public */ function setEndDate($date) @@ -3717,7 +3691,7 @@ class X509 /** * Set Serial Number * - * @param string $serial + * @param String $serial * @param $base optional * @access public */ @@ -3740,10 +3714,10 @@ class X509 * Get a reference to a subarray * * @param array $root - * @param string $path absolute path with / as component separator - * @param bool $create optional + * @param String $path absolute path with / as component separator + * @param Boolean $create optional * @access private - * @return array|false + * @return array item ref or false */ function &_subArray(&$root, $path, $create = false) { @@ -3776,10 +3750,10 @@ class X509 * Get a reference to an extension subarray * * @param array $root - * @param string $path optional absolute path with / as component separator - * @param bool $create optional + * @param String $path optional absolute path with / as component separator + * @param Boolean $create optional * @access private - * @return array|false + * @return array ref or false */ function &_extensions(&$root, $path = null, $create = false) { @@ -3830,10 +3804,10 @@ class X509 /** * Remove an Extension * - * @param string $id - * @param string $path optional + * @param String $id + * @param String $path optional * @access private - * @return bool + * @return Boolean */ function _removeExtension($id, $path = null) { @@ -3860,11 +3834,11 @@ class X509 * * Returns the extension if it exists and false if not * - * @param string $id - * @param array $cert optional - * @param string $path optional + * @param String $id + * @param Array $cert optional + * @param String $path optional * @access private - * @return mixed + * @return Mixed */ function _getExtension($id, $cert = null, $path = null) { @@ -3887,9 +3861,9 @@ class X509 * Returns a list of all extensions in use * * @param array $cert optional - * @param string $path optional + * @param String $path optional * @access private - * @return array + * @return Array */ function _getExtensions($cert = null, $path = null) { @@ -3908,13 +3882,13 @@ class X509 /** * Set an Extension * - * @param string $id - * @param mixed $value - * @param bool $critical optional - * @param bool $replace optional - * @param string $path optional + * @param String $id + * @param Mixed $value + * @param Boolean $critical optional + * @param Boolean $replace optional + * @param String $path optional * @access private - * @return bool + * @return Boolean */ function _setExtension($id, $value, $critical = false, $replace = true, $path = null) { @@ -3944,9 +3918,9 @@ class X509 /** * Remove a certificate, CSR or CRL Extension * - * @param string $id + * @param String $id * @access public - * @return bool + * @return Boolean */ function removeExtension($id) { @@ -3958,10 +3932,10 @@ class X509 * * Returns the extension if it exists and false if not * - * @param string $id - * @param array $cert optional + * @param String $id + * @param Array $cert optional * @access public - * @return mixed + * @return Mixed */ function getExtension($id, $cert = null) { @@ -3973,7 +3947,7 @@ class X509 * * @param array $cert optional * @access public - * @return array + * @return Array */ function getExtensions($cert = null) { @@ -3983,12 +3957,12 @@ class X509 /** * Set a certificate, CSR or CRL Extension * - * @param string $id - * @param mixed $value - * @param bool $critical optional - * @param bool $replace optional + * @param String $id + * @param Mixed $value + * @param Boolean $critical optional + * @param Boolean $replace optional * @access public - * @return bool + * @return Boolean */ function setExtension($id, $value, $critical = false, $replace = true) { @@ -3998,10 +3972,10 @@ class X509 /** * Remove a CSR attribute. * - * @param string $id - * @param int $disposition optional + * @param String $id + * @param Integer $disposition optional * @access public - * @return bool + * @return Boolean */ function removeAttribute($id, $disposition = self::ATTR_ALL) { @@ -4048,11 +4022,11 @@ class X509 * * Returns the attribute if it exists and false if not * - * @param string $id - * @param int $disposition optional - * @param array $csr optional + * @param String $id + * @param Integer $disposition optional + * @param Array $csr optional * @access public - * @return mixed + * @return Mixed */ function getAttribute($id, $disposition = self::ATTR_ALL, $csr = null) { @@ -4092,7 +4066,7 @@ class X509 * * @param array $csr optional * @access public - * @return array + * @return Array */ function getAttributes($csr = null) { @@ -4115,11 +4089,11 @@ class X509 /** * Set a CSR attribute * - * @param string $id - * @param mixed $value - * @param bool $disposition optional + * @param String $id + * @param Mixed $value + * @param Boolean $disposition optional * @access public - * @return bool + * @return Boolean */ function setAttribute($id, $value, $disposition = self::ATTR_ALL) { @@ -4173,7 +4147,7 @@ class X509 * * This is used by the id-ce-authorityKeyIdentifier and the id-ce-subjectKeyIdentifier extensions. * - * @param string $value + * @param String $value * @access public */ function setKeyIdentifier($value) @@ -4198,10 +4172,10 @@ class X509 * - \phpseclib\File\ASN1\Element object * - PEM or DER string * - * @param mixed $key optional - * @param int $method optional + * @param Mixed $key optional + * @param Integer $method optional * @access public - * @return string binary key identifier + * @return String binary key identifier */ function computeKeyIdentifier($key = null, $method = 1) { @@ -4232,7 +4206,7 @@ class X509 $raw = base64_decode($raw); // If the key is private, compute identifier from its corresponding public key. $key = new RSA(); - if (!$key->load($raw)) { + if (!$key->loadKey($raw)) { return false; // Not an unencrypted RSA key. } if ($key->getPrivateKey() !== false) { // If private. @@ -4252,7 +4226,7 @@ class X509 } return false; default: // Should be a key object (i.e.: \phpseclib\Crypt\RSA). - $key = $key->getPublicKey('PKCS1'); + $key = $key->getPublicKey(RSA::PUBLIC_FORMAT_PKCS1); break; } @@ -4275,7 +4249,7 @@ class X509 * Format a public key as appropriate * * @access private - * @return array + * @return Array */ function _formatSubjectPublicKey() { @@ -4285,7 +4259,7 @@ class X509 //return new Element(base64_decode(preg_replace('#-.+-|[\r\n]#', '', $this->publicKey->getPublicKey()))); return array( 'algorithm' => array('algorithm' => 'rsaEncryption'), - 'subjectPublicKey' => $this->publicKey->getPublicKey('PKCS1') + 'subjectPublicKey' => $this->publicKey->getPublicKey(RSA::PUBLIC_FORMAT_PKCS1) ); } @@ -4296,7 +4270,7 @@ class X509 * Set the domain name's which the cert is to be valid for * * @access public - * @return array + * @return Array */ function setDomain() { @@ -4309,7 +4283,7 @@ class X509 * Set the IP Addresses's which the cert is to be valid for * * @access public - * @param string $ipAddress optional + * @param String $ipAddress optional */ function setIPAddress() { @@ -4326,8 +4300,8 @@ class X509 * Helper function to build domain array * * @access private - * @param string $domain - * @return array + * @param String $domain + * @return Array */ function _dnsName($domain) { @@ -4340,8 +4314,8 @@ class X509 * (IPv6 is not currently supported) * * @access private - * @param string $address - * @return array + * @param String $address + * @return Array */ function _iPAddress($address) { @@ -4352,10 +4326,10 @@ class X509 * Get the index of a revoked certificate. * * @param array $rclist - * @param string $serial - * @param bool $create optional + * @param String $serial + * @param Boolean $create optional * @access private - * @return int|false + * @return Integer or false */ function _revokedCertificate(&$rclist, $serial, $create = false) { @@ -4380,10 +4354,10 @@ class X509 /** * Revoke a certificate. * - * @param string $serial - * @param string $date optional + * @param String $serial + * @param String $date optional * @access public - * @return bool + * @return Boolean */ function revoke($serial, $date = null) { @@ -4407,9 +4381,9 @@ class X509 /** * Unrevoke a certificate. * - * @param string $serial + * @param String $serial * @access public - * @return bool + * @return Boolean */ function unrevoke($serial) { @@ -4427,9 +4401,9 @@ class X509 /** * Get a revoked certificate. * - * @param string $serial + * @param String $serial * @access public - * @return mixed + * @return Mixed */ function getRevoked($serial) { @@ -4473,10 +4447,10 @@ class X509 /** * Remove a Revoked Certificate Extension * - * @param string $serial - * @param string $id + * @param String $serial + * @param String $id * @access public - * @return bool + * @return Boolean */ function removeRevokedCertificateExtension($serial, $id) { @@ -4494,11 +4468,11 @@ class X509 * * Returns the extension if it exists and false if not * - * @param string $serial - * @param string $id - * @param array $crl optional + * @param String $serial + * @param String $id + * @param Array $crl optional * @access public - * @return mixed + * @return Mixed */ function getRevokedCertificateExtension($serial, $id, $crl = null) { @@ -4518,10 +4492,10 @@ class X509 /** * Returns a list of all extensions in use for a given revoked certificate * - * @param string $serial + * @param String $serial * @param array $crl optional * @access public - * @return array + * @return Array */ function getRevokedCertificateExtensions($serial, $crl = null) { @@ -4541,13 +4515,13 @@ class X509 /** * Set a Revoked Certificate Extension * - * @param string $serial - * @param string $id - * @param mixed $value - * @param bool $critical optional - * @param bool $replace optional + * @param String $serial + * @param String $id + * @param Mixed $value + * @param Boolean $critical optional + * @param Boolean $replace optional * @access public - * @return bool + * @return Boolean */ function setRevokedCertificateExtension($serial, $id, $value, $critical = false, $replace = true) { @@ -4566,8 +4540,8 @@ class X509 * Extract raw BER from Base64 encoding * * @access private - * @param string $str - * @return string + * @param String $str + * @return String */ function _extractBER($str) { @@ -4580,7 +4554,7 @@ class X509 * subject=/O=organization/OU=org unit/CN=common name * issuer=/O=organization/CN=common name */ - $temp = preg_replace('#.*?^-+[^-]+-+[\r\n ]*$#ms', '', $str, 1); + $temp = preg_replace('#.*?^-+[^-]+-+#ms', '', $str, 1); // remove the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- stuff $temp = preg_replace('#-+[^-]+-+#', '', $temp); // remove new lines @@ -4588,31 +4562,4 @@ class X509 $temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? base64_decode($temp) : false; return $temp != false ? $temp : $str; } - - /** - * Returns the OID corresponding to a name - * - * What's returned in the associative array returned by loadX509() (or load*()) is either a name or an OID if - * no OID to name mapping is available. The problem with this is that what may be an unmapped OID in one version - * of phpseclib may not be unmapped in the next version, so apps that are looking at this OID may not be able - * to work from version to version. - * - * This method will return the OID if a name is passed to it and if no mapping is avialable it'll assume that - * what's being passed to it already is an OID and return that instead. A few examples. - * - * getOID('2.16.840.1.101.3.4.2.1') == '2.16.840.1.101.3.4.2.1' - * getOID('id-sha256') == '2.16.840.1.101.3.4.2.1' - * getOID('zzz') == 'zzz' - * - * @access public - * @return string - */ - function getOID($name) - { - static $reverseMap; - if (!isset($reverseMap)) { - $reverseMap = array_flip($this->oids); - } - return isset($reverseMap[$name]) ? $reverseMap[$name] : $name; - } } diff --git a/phpseclib/Math/BigInteger.php b/phpseclib/Math/BigInteger.php index bde7213d..bc7b2269 100644 --- a/phpseclib/Math/BigInteger.php +++ b/phpseclib/Math/BigInteger.php @@ -75,19 +75,19 @@ class BigInteger const MONTGOMERY = 0; /** * @see BigInteger::_barrett() - */ + */ const BARRETT = 1; /** * @see BigInteger::_mod2() - */ + */ const POWEROF2 = 2; /** * @see BigInteger::_remainder() - */ + */ const CLASSIC = 3; /** * @see BigInteger::__clone() - */ + */ const NONE = 4; /**#@-*/ @@ -101,11 +101,11 @@ class BigInteger */ /** * $result[self::VALUE] contains the value. - */ + */ const VALUE = 0; /** * $result[self::SIGN] contains the sign. - */ + */ const SIGN = 1; /**#@-*/ @@ -118,11 +118,11 @@ class BigInteger * Cache constants * * $cache[self::VARIABLE] tells us whether or not the cached data is still valid. - */ + */ const VARIABLE = 0; /** * $cache[self::DATA] contains the cached data. - */ + */ const DATA = 1; /**#@-*/ @@ -134,19 +134,19 @@ class BigInteger */ /** * To use the pure-PHP implementation - */ + */ const MODE_INTERNAL = 1; /** * To use the BCMath library * * (if enabled; otherwise, the internal implementation will be used) - */ + */ const MODE_BCMATH = 2; /** * To use the GMP library * * (if present; otherwise, either the BCMath or the internal implementation will be used) - */ + */ const MODE_GMP = 3; /**#@-*/ @@ -156,7 +156,7 @@ class BigInteger * At what point do we switch between Karatsuba multiplication and schoolbook long multiplication? * * @access private - */ + */ const KARATSUBA_CUTOFF = 25; /**#@+ @@ -172,13 +172,13 @@ class BigInteger /** * $max10 in greatest $max10Len satisfying * $max10 = 10**$max10Len <= 2**$base. - */ + */ protected static $max10; /** * $max10Len in greatest $max10Len satisfying * $max10 = 10**$max10Len <= 2**$base. - */ + */ protected static $max10Len; protected static $maxDigit2; /**#@-*/ @@ -186,7 +186,7 @@ class BigInteger /** * Holds the BigInteger's value. * - * @var array + * @var Array * @access private */ var $value; @@ -194,15 +194,22 @@ class BigInteger /** * Holds the BigInteger's magnitude. * - * @var bool + * @var Boolean * @access private */ var $is_negative = false; + /** + * Random number generator function + * + * @access private + */ + var $generator = 'mt_rand'; + /** * Precision * - * @see self::setPrecision() + * @see setPrecision() * @access private */ var $precision = -1; @@ -210,7 +217,7 @@ class BigInteger /** * Precision Bitmask * - * @see self::setPrecision() + * @see setPrecision() * @access private */ var $bitmask = false; @@ -222,9 +229,9 @@ class BigInteger * a variable that'll be serializable regardless of whether or not extensions are being used. Unlike $this->value, * however, $this->hex is only calculated when $this->__sleep() is called. * - * @see self::__sleep() - * @see self::__wakeup() - * @var string + * @see __sleep() + * @see __wakeup() + * @var String * @access private */ var $hex; @@ -244,8 +251,8 @@ class BigInteger * ?> * * - * @param $x base-10 number or base-$base number if $base set. - * @param int $base + * @param optional $x base-10 number or base-$base number if $base set. + * @param optional integer $base * @return \phpseclib\Math\BigInteger * @access public */ @@ -264,7 +271,7 @@ class BigInteger } } - if (extension_loaded('openssl') && !defined('MATH_BIGINTEGER_OPENSSL_DISABLE') && !defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) { + if (function_exists('openssl_public_encrypt') && !defined('MATH_BIGINTEGER_OPENSSL_DISABLE') && !defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) { // some versions of XAMPP have mismatched versions of OpenSSL which causes it not to work ob_start(); @phpinfo(); @@ -323,6 +330,7 @@ class BigInteger self::$max10 = 10000000; self::$max10Len = 7; self::$maxDigit2 = pow(2, 52); // pow() prevents truncation + break; } } @@ -415,13 +423,13 @@ class BigInteger $this->is_negative = false; break; case self::MODE_BCMATH: - $x = (strlen($x) & 1) ? '0' . $x : $x; + $x = ( strlen($x) & 1 ) ? '0' . $x : $x; $temp = new static(pack('H*', $x), 256); $this->value = $this->is_negative ? '-' . $temp->value : $temp->value; $this->is_negative = false; break; default: - $x = (strlen($x) & 1) ? '0' . $x : $x; + $x = ( strlen($x) & 1 ) ? '0' . $x : $x; $temp = new static(pack('H*', $x), 256); $this->value = $temp->value; } @@ -514,8 +522,8 @@ class BigInteger * ?> * * - * @param bool $twos_compliment - * @return string + * @param Boolean $twos_compliment + * @return String * @access public * @internal Converts a base-2**26 number to base-2**8 */ @@ -527,7 +535,7 @@ class BigInteger return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : ''; } - $temp = $comparison < 0 ? $this->add(new static(1)) : $this; + $temp = $comparison < 0 ? $this->add(new static(1)) : $this->copy(); $bytes = $temp->toBytes(); if (empty($bytes)) { // eg. if the number we're trying to convert is -1 @@ -548,7 +556,7 @@ class BigInteger } $temp = gmp_strval(gmp_abs($this->value), 16); - $temp = (strlen($temp) & 1) ? '0' . $temp : $temp; + $temp = ( strlen($temp) & 1 ) ? '0' . $temp : $temp; $temp = pack('H*', $temp); return $this->precision > 0 ? @@ -580,11 +588,13 @@ class BigInteger if (!count($this->value)) { return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : ''; } - $result = self::_int2bytes($this->value[count($this->value) - 1]); + $result = $this->_int2bytes($this->value[count($this->value) - 1]); - for ($i = count($this->value) - 2; $i >= 0; --$i) { - self::_base256_lshift($result, self::$base); - $result = $result | str_pad(self::_int2bytes($this->value[$i]), strlen($result), chr(0), STR_PAD_LEFT); + $temp = $this->copy(); + + for ($i = count($temp->value) - 2; $i >= 0; --$i) { + $temp->_base256_lshift($result, self::$base); + $result = $result | str_pad($temp->_int2bytes($temp->value[$i]), strlen($result), chr(0), STR_PAD_LEFT); } return $this->precision > 0 ? @@ -607,8 +617,8 @@ class BigInteger * ?> * * - * @param bool $twos_compliment - * @return string + * @param Boolean $twos_compliment + * @return String * @access public * @internal Converts a base-2**26 number to base-2**8 */ @@ -632,8 +642,8 @@ class BigInteger * ?> * * - * @param bool $twos_compliment - * @return string + * @param Boolean $twos_compliment + * @return String * @access public * @internal Converts a base-2**26 number to base-2**2 */ @@ -668,7 +678,7 @@ class BigInteger * ?> * * - * @return string + * @return String * @access public * @internal Converts a base-2**26 number to base-10**7 (which is pretty much base-10) */ @@ -689,7 +699,7 @@ class BigInteger return '0'; } - $temp = clone $this; + $temp = $this->copy(); $temp->is_negative = false; $divisor = new static(); @@ -711,6 +721,29 @@ class BigInteger return $result; } + /** + * Copy an object + * + * PHP5 passes objects by reference while PHP4 passes by value. As such, we need a function to guarantee + * that all objects are passed by value, when appropriate. More information can be found here: + * + * {@link http://php.net/language.oop5.basic#51624} + * + * @access public + * @see __clone() + * @return \phpseclib\Math\BigInteger + */ + function copy() + { + $temp = new static(); + $temp->value = $this->value; + $temp->is_negative = $this->is_negative; + $temp->generator = $this->generator; + $temp->precision = $this->precision; + $temp->bitmask = $this->bitmask; + return $temp; + } + /** * __toString() magic method * @@ -725,22 +758,43 @@ class BigInteger return $this->toString(); } + /** + * __clone() magic method + * + * Although you can call BigInteger::__toString() directly in PHP5, you cannot call BigInteger::__clone() directly + * in PHP5. You can in PHP4 since it's not a magic method, but in PHP5, you have to call it by using the PHP5 + * only syntax of $y = clone $x. As such, if you're trying to write an application that works on both PHP4 and + * PHP5, call BigInteger::copy(), instead. + * + * @access public + * @see copy() + * @return \phpseclib\Math\BigInteger + */ + function __clone() + { + return $this->copy(); + } + /** * __sleep() magic method * * Will be called, automatically, when serialize() is called on a BigInteger object. * - * @see self::__wakeup() + * @see __wakeup() * @access public */ function __sleep() { $this->hex = $this->toHex(true); $vars = array('hex'); + if ($this->generator != 'mt_rand') { + $vars[] = 'generator'; + } if ($this->precision > 0) { $vars[] = 'precision'; } return $vars; + } /** @@ -748,7 +802,7 @@ class BigInteger * * Will be called, automatically, when unserialize() is called on a BigInteger object. * - * @see self::__sleep() + * @see __sleep() * @access public */ function __wakeup() @@ -762,39 +816,6 @@ class BigInteger } } - /** - * __debugInfo() magic method - * - * Will be called, automatically, when print_r() or var_dump() are called - * - * @access public - */ - function __debugInfo() - { - $opts = array(); - switch (MATH_BIGINTEGER_MODE) { - case self::MODE_GMP: - $engine = 'gmp'; - break; - case self::MODE_BCMATH: - $engine = 'bcmath'; - break; - case self::MODE_INTERNAL: - $engine = 'internal'; - $opts[] = PHP_INT_SIZE == 8 ? '64-bit' : '32-bit'; - } - if (MATH_BIGINTEGER_MODE != self::MODE_GMP && defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) { - $opts[] = 'OpenSSL'; - } - if (!empty($opts)) { - $engine.= ' (' . implode($opts, ', ') . ')'; - } - return array( - 'value' => '0x' . $this->toHex(true), - 'engine' => $engine - ); - } - /** * Adds two BigIntegers. * @@ -815,7 +836,7 @@ class BigInteger * @access public * @internal Performs base-2**52 addition */ - function add(BigInteger $y) + function add($y) { switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: @@ -830,7 +851,7 @@ class BigInteger return $this->_normalize($temp); } - $temp = self::_add($this->value, $this->is_negative, $y->value, $y->is_negative); + $temp = $this->_add($this->value, $this->is_negative, $y->value, $y->is_negative); $result = new static(); $result->value = $temp[self::VALUE]; @@ -842,14 +863,14 @@ class BigInteger /** * Performs addition. * - * @param array $x_value - * @param bool $x_negative - * @param array $y_value - * @param bool $y_negative - * @return array + * @param Array $x_value + * @param Boolean $x_negative + * @param Array $y_value + * @param Boolean $y_negative + * @return Array * @access private */ - static function _add($x_value, $x_negative, $y_value, $y_negative) + function _add($x_value, $x_negative, $y_value, $y_negative) { $x_size = count($x_value); $y_size = count($y_value); @@ -875,8 +896,8 @@ class BigInteger ); } - $temp = self::_subtract($x_value, false, $y_value, false); - $temp[self::SIGN] = self::_compare($x_value, false, $y_value, false) > 0 ? + $temp = $this->_subtract($x_value, false, $y_value, false); + $temp[self::SIGN] = $this->_compare($x_value, false, $y_value, false) > 0 ? $x_negative : $y_negative; return $temp; @@ -919,7 +940,7 @@ class BigInteger } return array( - self::VALUE => self::_trim($value), + self::VALUE => $this->_trim($value), self::SIGN => $x_negative ); } @@ -944,7 +965,7 @@ class BigInteger * @access public * @internal Performs base-2**52 subtraction */ - function subtract(BigInteger $y) + function subtract($y) { switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: @@ -959,7 +980,7 @@ class BigInteger return $this->_normalize($temp); } - $temp = self::_subtract($this->value, $this->is_negative, $y->value, $y->is_negative); + $temp = $this->_subtract($this->value, $this->is_negative, $y->value, $y->is_negative); $result = new static(); $result->value = $temp[self::VALUE]; @@ -971,14 +992,14 @@ class BigInteger /** * Performs subtraction. * - * @param array $x_value - * @param bool $x_negative - * @param array $y_value - * @param bool $y_negative - * @return array + * @param Array $x_value + * @param Boolean $x_negative + * @param Array $y_value + * @param Boolean $y_negative + * @return Array * @access private */ - static function _subtract($x_value, $x_negative, $y_value, $y_negative) + function _subtract($x_value, $x_negative, $y_value, $y_negative) { $x_size = count($x_value); $y_size = count($y_value); @@ -997,13 +1018,13 @@ class BigInteger // add, if appropriate (ie. -$x - +$y or +$x - -$y) if ($x_negative != $y_negative) { - $temp = self::_add($x_value, false, $y_value, false); + $temp = $this->_add($x_value, false, $y_value, false); $temp[self::SIGN] = $x_negative; return $temp; } - $diff = self::_compare($x_value, $x_negative, $y_value, $y_negative); + $diff = $this->_compare($x_value, $x_negative, $y_value, $y_negative); if (!$diff) { return array( @@ -1053,7 +1074,7 @@ class BigInteger } return array( - self::VALUE => self::_trim($x_value), + self::VALUE => $this->_trim($x_value), self::SIGN => $x_negative ); } @@ -1077,7 +1098,7 @@ class BigInteger * @return \phpseclib\Math\BigInteger * @access public */ - function multiply(BigInteger $x) + function multiply($x) { switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: @@ -1092,7 +1113,7 @@ class BigInteger return $this->_normalize($temp); } - $temp = self::_multiply($this->value, $this->is_negative, $x->value, $x->is_negative); + $temp = $this->_multiply($this->value, $this->is_negative, $x->value, $x->is_negative); $product = new static(); $product->value = $temp[self::VALUE]; @@ -1104,14 +1125,14 @@ class BigInteger /** * Performs multiplication. * - * @param array $x_value - * @param bool $x_negative - * @param array $y_value - * @param bool $y_negative - * @return array + * @param Array $x_value + * @param Boolean $x_negative + * @param Array $y_value + * @param Boolean $y_negative + * @return Array * @access private */ - static function _multiply($x_value, $x_negative, $y_value, $y_negative) + function _multiply($x_value, $x_negative, $y_value, $y_negative) { //if ( $x_value == $y_value ) { // return array( @@ -1132,8 +1153,8 @@ class BigInteger return array( self::VALUE => min($x_length, $y_length) < 2 * self::KARATSUBA_CUTOFF ? - self::_trim(self::_regularMultiply($x_value, $y_value)) : - self::_trim(self::_karatsuba($x_value, $y_value)), + $this->_trim($this->_regularMultiply($x_value, $y_value)) : + $this->_trim($this->_karatsuba($x_value, $y_value)), self::SIGN => $x_negative != $y_negative ); } @@ -1143,12 +1164,12 @@ class BigInteger * * Modeled after 'multiply' in MutableBigInteger.java. * - * @param array $x_value - * @param array $y_value - * @return array + * @param Array $x_value + * @param Array $y_value + * @return Array * @access private */ - static function _regularMultiply($x_value, $y_value) + function _regularMultiply($x_value, $y_value) { $x_length = count($x_value); $y_length = count($y_value); @@ -1166,7 +1187,7 @@ class BigInteger $y_length = count($y_value); } - $product_value = self::_array_repeat(0, $x_length + $y_length); + $product_value = $this->_array_repeat(0, $x_length + $y_length); // the following for loop could be removed if the for loop following it // (the one with nested for loops) initially set $i to 0, but @@ -1207,17 +1228,17 @@ class BigInteger * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=120 MPM 5.2.3}. * - * @param array $x_value - * @param array $y_value - * @return array + * @param Array $x_value + * @param Array $y_value + * @return Array * @access private */ - static function _karatsuba($x_value, $y_value) + function _karatsuba($x_value, $y_value) { $m = min(count($x_value) >> 1, count($y_value) >> 1); if ($m < self::KARATSUBA_CUTOFF) { - return self::_regularMultiply($x_value, $y_value); + return $this->_regularMultiply($x_value, $y_value); } $x1 = array_slice($x_value, $m); @@ -1225,20 +1246,20 @@ class BigInteger $y1 = array_slice($y_value, $m); $y0 = array_slice($y_value, 0, $m); - $z2 = self::_karatsuba($x1, $y1); - $z0 = self::_karatsuba($x0, $y0); + $z2 = $this->_karatsuba($x1, $y1); + $z0 = $this->_karatsuba($x0, $y0); - $z1 = self::_add($x1, false, $x0, false); - $temp = self::_add($y1, false, $y0, false); - $z1 = self::_karatsuba($z1[self::VALUE], $temp[self::VALUE]); - $temp = self::_add($z2, false, $z0, false); - $z1 = self::_subtract($z1, false, $temp[self::VALUE], false); + $z1 = $this->_add($x1, false, $x0, false); + $temp = $this->_add($y1, false, $y0, false); + $z1 = $this->_karatsuba($z1[self::VALUE], $temp[self::VALUE]); + $temp = $this->_add($z2, false, $z0, false); + $z1 = $this->_subtract($z1, false, $temp[self::VALUE], false); $z2 = array_merge(array_fill(0, 2 * $m, 0), $z2); $z1[self::VALUE] = array_merge(array_fill(0, $m, 0), $z1[self::VALUE]); - $xy = self::_add($z2, false, $z1[self::VALUE], $z1[self::SIGN]); - $xy = self::_add($xy[self::VALUE], $xy[self::SIGN], $z0, false); + $xy = $this->_add($z2, false, $z1[self::VALUE], $z1[self::SIGN]); + $xy = $this->_add($xy[self::VALUE], $xy[self::SIGN], $z0, false); return $xy[self::VALUE]; } @@ -1246,15 +1267,15 @@ class BigInteger /** * Performs squaring * - * @param array $x - * @return array + * @param Array $x + * @return Array * @access private */ - static function _square($x = false) + function _square($x = false) { return count($x) < 2 * self::KARATSUBA_CUTOFF ? - self::_trim(self::_baseSquare($x)) : - self::_trim(self::_karatsubaSquare($x)); + $this->_trim($this->_baseSquare($x)) : + $this->_trim($this->_karatsubaSquare($x)); } /** @@ -1264,16 +1285,16 @@ class BigInteger * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=7 HAC 14.2.4} / * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=141 MPM 5.3} for more information. * - * @param array $value - * @return array + * @param Array $value + * @return Array * @access private */ - static function _baseSquare($value) + function _baseSquare($value) { if (empty($value)) { return array(); } - $square_value = self::_array_repeat(0, 2 * count($value)); + $square_value = $this->_array_repeat(0, 2 * count($value)); for ($i = 0, $max_index = count($value) - 1; $i <= $max_index; ++$i) { $i2 = $i << 1; @@ -1303,34 +1324,34 @@ class BigInteger * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=151 MPM 5.3.4}. * - * @param array $value - * @return array + * @param Array $value + * @return Array * @access private */ - static function _karatsubaSquare($value) + function _karatsubaSquare($value) { $m = count($value) >> 1; if ($m < self::KARATSUBA_CUTOFF) { - return self::_baseSquare($value); + return $this->_baseSquare($value); } $x1 = array_slice($value, $m); $x0 = array_slice($value, 0, $m); - $z2 = self::_karatsubaSquare($x1); - $z0 = self::_karatsubaSquare($x0); + $z2 = $this->_karatsubaSquare($x1); + $z0 = $this->_karatsubaSquare($x0); - $z1 = self::_add($x1, false, $x0, false); - $z1 = self::_karatsubaSquare($z1[self::VALUE]); - $temp = self::_add($z2, false, $z0, false); - $z1 = self::_subtract($z1, false, $temp[self::VALUE], false); + $z1 = $this->_add($x1, false, $x0, false); + $z1 = $this->_karatsubaSquare($z1[self::VALUE]); + $temp = $this->_add($z2, false, $z0, false); + $z1 = $this->_subtract($z1, false, $temp[self::VALUE], false); $z2 = array_merge(array_fill(0, 2 * $m, 0), $z2); $z1[self::VALUE] = array_merge(array_fill(0, $m, 0), $z1[self::VALUE]); - $xx = self::_add($z2, false, $z1[self::VALUE], $z1[self::SIGN]); - $xx = self::_add($xx[self::VALUE], $xx[self::SIGN], $z0, false); + $xx = $this->_add($z2, false, $z1[self::VALUE], $z1[self::SIGN]); + $xx = $this->_add($xx[self::VALUE], $xx[self::SIGN], $z0, false); return $xx[self::VALUE]; } @@ -1358,11 +1379,11 @@ class BigInteger * * * @param \phpseclib\Math\BigInteger $y - * @return array + * @return Array * @access public * @internal This function is based off of {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=9 HAC 14.20}. */ - function divide(BigInteger $y) + function divide($y) { switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: @@ -1405,8 +1426,8 @@ class BigInteger $zero = new static(); } - $x = clone $this; - $y = clone $y; + $x = $this->copy(); + $y = $y->copy(); $x_sign = $x->is_negative; $y_sign = $y->is_negative; @@ -1474,7 +1495,7 @@ class BigInteger ); $y_window = array( $y_value[$y_max], - ($y_max > 0) ? $y_value[$y_max - 1] : 0 + ( $y_max > 0 ) ? $y_value[$y_max - 1] : 0 ); $q_index = $i - $y_max - 1; @@ -1538,19 +1559,19 @@ class BigInteger * * abc / x = a00 / x + b0 / x + c / x * - * @param array $dividend - * @param array $divisor - * @return array + * @param Array $dividend + * @param Array $divisor + * @return Array * @access private */ - static function _divide_digit($dividend, $divisor) + function _divide_digit($dividend, $divisor) { $carry = 0; $result = array(); for ($i = count($dividend) - 1; $i >= 0; --$i) { $temp = self::$baseFull * $carry + $dividend[$i]; - $result[$i] = self::_safe_divide($temp, $divisor); + $result[$i] = $this->_safe_divide($temp, $divisor); $carry = (int) ($temp - $divisor * $result[$i]); } @@ -1597,7 +1618,7 @@ class BigInteger * the other, a power of two - and recombine them, later. This is the method that this modPow function uses. * {@link http://islab.oregonstate.edu/papers/j34monex.pdf Montgomery Reduction with Even Modulus} elaborates. */ - function modPow(BigInteger $e, BigInteger $n) + function modPow($e, $n) { $n = $this->bitmask !== false && $this->bitmask->compare($n) < 0 ? $this->bitmask : $n->abs(); @@ -1631,26 +1652,26 @@ class BigInteger ); $components = array( - 'modulus' => pack('Ca*a*', 2, self::_encodeASN1Length(strlen($components['modulus'])), $components['modulus']), - 'publicExponent' => pack('Ca*a*', 2, self::_encodeASN1Length(strlen($components['publicExponent'])), $components['publicExponent']) + 'modulus' => pack('Ca*a*', 2, $this->_encodeASN1Length(strlen($components['modulus'])), $components['modulus']), + 'publicExponent' => pack('Ca*a*', 2, $this->_encodeASN1Length(strlen($components['publicExponent'])), $components['publicExponent']) ); $RSAPublicKey = pack( 'Ca*a*a*', 48, - self::_encodeASN1Length(strlen($components['modulus']) + strlen($components['publicExponent'])), + $this->_encodeASN1Length(strlen($components['modulus']) + strlen($components['publicExponent'])), $components['modulus'], $components['publicExponent'] ); $rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA $RSAPublicKey = chr(0) . $RSAPublicKey; - $RSAPublicKey = chr(3) . self::_encodeASN1Length(strlen($RSAPublicKey)) . $RSAPublicKey; + $RSAPublicKey = chr(3) . $this->_encodeASN1Length(strlen($RSAPublicKey)) . $RSAPublicKey; $encapsulated = pack( 'Ca*a*', 48, - self::_encodeASN1Length(strlen($rsaOID . $RSAPublicKey)), + $this->_encodeASN1Length(strlen($rsaOID . $RSAPublicKey)), $rsaOID . $RSAPublicKey ); @@ -1666,10 +1687,10 @@ class BigInteger } if (MATH_BIGINTEGER_MODE == self::MODE_BCMATH) { - $temp = new static(); - $temp->value = bcpowmod($this->value, $e->value, $n->value, 0); + $temp = new static(); + $temp->value = bcpowmod($this->value, $e->value, $n->value, 0); - return $this->_normalize($temp); + return $this->_normalize($temp); } if (empty($e->value)) { @@ -1685,7 +1706,7 @@ class BigInteger if ($e->value == array(2)) { $temp = new static(); - $temp->value = self::_square($this->value); + $temp->value = $this->_square($this->value); list(, $temp) = $temp->divide($n); return $this->_normalize($temp); } @@ -1714,13 +1735,13 @@ class BigInteger } // at this point, 2^$j * $n/(2^$j) == $n - $mod1 = clone $n; + $mod1 = $n->copy(); $mod1->_rshift($j); $mod2 = new static(); $mod2->value = array(1); $mod2->_lshift($j); - $part1 = ($mod1->value != array(1)) ? $this->_slidingWindow($e, $mod1, self::MONTGOMERY) : new static(); + $part1 = ( $mod1->value != array(1) ) ? $this->_slidingWindow($e, $mod1, self::MONTGOMERY) : new static(); $part2 = $this->_slidingWindow($e, $mod2, self::POWEROF2); $y1 = $mod2->modInverse($mod1); @@ -1748,7 +1769,7 @@ class BigInteger * @return \phpseclib\Math\BigInteger * @access public */ - function powMod(BigInteger $e, BigInteger $n) + function powMod($e, $n) { return $this->modPow($e, $n); } @@ -1763,7 +1784,7 @@ class BigInteger * * @param \phpseclib\Math\BigInteger $e * @param \phpseclib\Math\BigInteger $n - * @param int $mode + * @param Integer $mode * @return \phpseclib\Math\BigInteger * @access private */ @@ -1783,30 +1804,30 @@ class BigInteger // calculate the appropriate window size. // $window_size == 3 if $window_ranges is between 25 and 81, for example. - for ($i = 0, $window_size = 1; $i < count($window_ranges) && $e_length > $window_ranges[$i]; ++$window_size, ++$i) { + for ($i = 0, $window_size = 1; $e_length > $window_ranges[$i] && $i < count($window_ranges); ++$window_size, ++$i) { } $n_value = $n->value; // precompute $this^0 through $this^$window_size $powers = array(); - $powers[1] = self::_prepareReduce($this->value, $n_value, $mode); - $powers[2] = self::_squareReduce($powers[1], $n_value, $mode); + $powers[1] = $this->_prepareReduce($this->value, $n_value, $mode); + $powers[2] = $this->_squareReduce($powers[1], $n_value, $mode); // we do every other number since substr($e_bits, $i, $j+1) (see below) is supposed to end // in a 1. ie. it's supposed to be odd. $temp = 1 << ($window_size - 1); for ($i = 1; $i < $temp; ++$i) { $i2 = $i << 1; - $powers[$i2 + 1] = self::_multiplyReduce($powers[$i2 - 1], $powers[2], $n_value, $mode); + $powers[$i2 + 1] = $this->_multiplyReduce($powers[$i2 - 1], $powers[2], $n_value, $mode); } $result = array(1); - $result = self::_prepareReduce($result, $n_value, $mode); + $result = $this->_prepareReduce($result, $n_value, $mode); for ($i = 0; $i < $e_length;) { if (!$e_bits[$i]) { - $result = self::_squareReduce($result, $n_value, $mode); + $result = $this->_squareReduce($result, $n_value, $mode); ++$i; } else { for ($j = $window_size - 1; $j > 0; --$j) { @@ -1815,19 +1836,18 @@ class BigInteger } } - // eg. the length of substr($e_bits, $i, $j + 1) - for ($k = 0; $k <= $j; ++$k) { - $result = self::_squareReduce($result, $n_value, $mode); + for ($k = 0; $k <= $j; ++$k) {// eg. the length of substr($e_bits, $i, $j+1) + $result = $this->_squareReduce($result, $n_value, $mode); } - $result = self::_multiplyReduce($result, $powers[bindec(substr($e_bits, $i, $j + 1))], $n_value, $mode); + $result = $this->_multiplyReduce($result, $powers[bindec(substr($e_bits, $i, $j + 1))], $n_value, $mode); - $i += $j + 1; + $i+=$j + 1; } } $temp = new static(); - $temp->value = self::_reduce($result, $n_value, $mode); + $temp->value = $this->_reduce($result, $n_value, $mode); return $temp; } @@ -1837,20 +1857,20 @@ class BigInteger * * For most $modes this will return the remainder. * - * @see self::_slidingWindow() + * @see _slidingWindow() * @access private - * @param array $x - * @param array $n - * @param int $mode - * @return array + * @param Array $x + * @param Array $n + * @param Integer $mode + * @return Array */ - static function _reduce($x, $n, $mode) + function _reduce($x, $n, $mode) { switch ($mode) { case self::MONTGOMERY: - return self::_montgomery($x, $n); + return $this->_montgomery($x, $n); case self::BARRETT: - return self::_barrett($x, $n); + return $this->_barrett($x, $n); case self::POWEROF2: $lhs = new static(); $lhs->value = $x; @@ -1874,57 +1894,57 @@ class BigInteger /** * Modular reduction preperation * - * @see self::_slidingWindow() + * @see _slidingWindow() * @access private - * @param array $x - * @param array $n - * @param int $mode - * @return array + * @param Array $x + * @param Array $n + * @param Integer $mode + * @return Array */ - static function _prepareReduce($x, $n, $mode) + function _prepareReduce($x, $n, $mode) { if ($mode == self::MONTGOMERY) { - return self::_prepMontgomery($x, $n); + return $this->_prepMontgomery($x, $n); } - return self::_reduce($x, $n, $mode); + return $this->_reduce($x, $n, $mode); } /** * Modular multiply * - * @see self::_slidingWindow() + * @see _slidingWindow() * @access private - * @param array $x - * @param array $y - * @param array $n - * @param int $mode - * @return array + * @param Array $x + * @param Array $y + * @param Array $n + * @param Integer $mode + * @return Array */ - static function _multiplyReduce($x, $y, $n, $mode) + function _multiplyReduce($x, $y, $n, $mode) { if ($mode == self::MONTGOMERY) { - return self::_montgomeryMultiply($x, $y, $n); + return $this->_montgomeryMultiply($x, $y, $n); } - $temp = self::_multiply($x, false, $y, false); - return self::_reduce($temp[self::VALUE], $n, $mode); + $temp = $this->_multiply($x, false, $y, false); + return $this->_reduce($temp[self::VALUE], $n, $mode); } /** * Modular square * - * @see self::_slidingWindow() + * @see _slidingWindow() * @access private - * @param array $x - * @param array $n - * @param int $mode - * @return array + * @param Array $x + * @param Array $n + * @param Integer $mode + * @return Array */ - static function _squareReduce($x, $n, $mode) + function _squareReduce($x, $n, $mode) { if ($mode == self::MONTGOMERY) { - return self::_montgomeryMultiply($x, $x, $n); + return $this->_montgomeryMultiply($x, $x, $n); } - return self::_reduce(self::_square($x), $n, $mode); + return $this->_reduce($this->_square($x), $n, $mode); } /** @@ -1933,7 +1953,7 @@ class BigInteger * Calculates $x%$n, where $n = 2**$e, for some $e. Since this is basically the same as doing $x & ($n-1), * we'll just use this function as a wrapper for doing that. * - * @see self::_slidingWindow() + * @see _slidingWindow() * @access private * @param \phpseclib\Math\BigInteger * @return \phpseclib\Math\BigInteger @@ -1963,13 +1983,13 @@ class BigInteger * (x >> 1) + (x >> 1) != x / 2 + x / 2. If x is even, they're the same, but if x is odd, they're not. See the in-line * comments for details. * - * @see self::_slidingWindow() + * @see _slidingWindow() * @access private - * @param array $n - * @param array $m - * @return array + * @param Array $n + * @param Array $m + * @return Array */ - static function _barrett($n, $m) + function _barrett($n, $m) { static $cache = array( self::VARIABLE => array(), @@ -1978,7 +1998,7 @@ class BigInteger $m_length = count($m); - // if (self::_compare($n, self::_square($m)) >= 0) { + // if ($this->_compare($n, $this->_square($m)) >= 0) { if (count($n) > 2 * $m_length) { $lhs = new static(); $rhs = new static(); @@ -1990,7 +2010,7 @@ class BigInteger // if (m.length >> 1) + 2 <= m.length then m is too small and n can't be reduced if ($m_length < 5) { - return self::_regularBarrett($n, $m); + return $this->_regularBarrett($n, $m); } // n = 2 * m.length @@ -2001,7 +2021,7 @@ class BigInteger $lhs = new static(); $lhs_value = &$lhs->value; - $lhs_value = self::_array_repeat(0, $m_length + ($m_length >> 1)); + $lhs_value = $this->_array_repeat(0, $m_length + ($m_length >> 1)); $lhs_value[] = 1; $rhs = new static(); $rhs->value = $m; @@ -2021,34 +2041,34 @@ class BigInteger $cutoff = $m_length + ($m_length >> 1); $lsd = array_slice($n, 0, $cutoff); // m.length + (m.length >> 1) $msd = array_slice($n, $cutoff); // m.length >> 1 - $lsd = self::_trim($lsd); - $temp = self::_multiply($msd, false, $m1, false); - $n = self::_add($lsd, false, $temp[self::VALUE], false); // m.length + (m.length >> 1) + 1 + $lsd = $this->_trim($lsd); + $temp = $this->_multiply($msd, false, $m1, false); + $n = $this->_add($lsd, false, $temp[self::VALUE], false); // m.length + (m.length >> 1) + 1 if ($m_length & 1) { - return self::_regularBarrett($n[self::VALUE], $m); + return $this->_regularBarrett($n[self::VALUE], $m); } // (m.length + (m.length >> 1) + 1) - (m.length - 1) == (m.length >> 1) + 2 $temp = array_slice($n[self::VALUE], $m_length - 1); // if even: ((m.length >> 1) + 2) + (m.length >> 1) == m.length + 2 // if odd: ((m.length >> 1) + 2) + (m.length >> 1) == (m.length - 1) + 2 == m.length + 1 - $temp = self::_multiply($temp, false, $u, false); + $temp = $this->_multiply($temp, false, $u, false); // if even: (m.length + 2) - ((m.length >> 1) + 1) = m.length - (m.length >> 1) + 1 // if odd: (m.length + 1) - ((m.length >> 1) + 1) = m.length - (m.length >> 1) $temp = array_slice($temp[self::VALUE], ($m_length >> 1) + 1); // if even: (m.length - (m.length >> 1) + 1) + m.length = 2 * m.length - (m.length >> 1) + 1 // if odd: (m.length - (m.length >> 1)) + m.length = 2 * m.length - (m.length >> 1) - $temp = self::_multiply($temp, false, $m, false); + $temp = $this->_multiply($temp, false, $m, false); // at this point, if m had an odd number of digits, we'd be subtracting a 2 * m.length - (m.length >> 1) digit // number from a m.length + (m.length >> 1) + 1 digit number. ie. there'd be an extra digit and the while loop // following this comment would loop a lot (hence our calling _regularBarrett() in that situation). - $result = self::_subtract($n[self::VALUE], false, $temp[self::VALUE], false); + $result = $this->_subtract($n[self::VALUE], false, $temp[self::VALUE], false); - while (self::_compare($result[self::VALUE], $result[self::SIGN], $m, false) >= 0) { - $result = self::_subtract($result[self::VALUE], $result[self::SIGN], $m, false); + while ($this->_compare($result[self::VALUE], $result[self::SIGN], $m, false) >= 0) { + $result = $this->_subtract($result[self::VALUE], $result[self::SIGN], $m, false); } return $result[self::VALUE]; @@ -2060,13 +2080,13 @@ class BigInteger * For numbers with more than four digits BigInteger::_barrett() is faster. The difference between that and this * is that this function does not fold the denominator into a smaller form. * - * @see self::_slidingWindow() + * @see _slidingWindow() * @access private - * @param array $x - * @param array $n - * @return array + * @param Array $x + * @param Array $n + * @return Array */ - static function _regularBarrett($x, $n) + function _regularBarrett($x, $n) { static $cache = array( self::VARIABLE => array(), @@ -2089,7 +2109,7 @@ class BigInteger $cache[self::VARIABLE][] = $n; $lhs = new static(); $lhs_value = &$lhs->value; - $lhs_value = self::_array_repeat(0, 2 * $n_length); + $lhs_value = $this->_array_repeat(0, 2 * $n_length); $lhs_value[] = 1; $rhs = new static(); $rhs->value = $n; @@ -2100,27 +2120,27 @@ class BigInteger // 2 * m.length - (m.length - 1) = m.length + 1 $temp = array_slice($x, $n_length - 1); // (m.length + 1) + m.length = 2 * m.length + 1 - $temp = self::_multiply($temp, false, $cache[self::DATA][$key], false); + $temp = $this->_multiply($temp, false, $cache[self::DATA][$key], false); // (2 * m.length + 1) - (m.length - 1) = m.length + 2 $temp = array_slice($temp[self::VALUE], $n_length + 1); // m.length + 1 $result = array_slice($x, 0, $n_length + 1); // m.length + 1 - $temp = self::_multiplyLower($temp, false, $n, false, $n_length + 1); - // $temp == array_slice(self::_multiply($temp, false, $n, false)->value, 0, $n_length + 1) + $temp = $this->_multiplyLower($temp, false, $n, false, $n_length + 1); + // $temp == array_slice($temp->_multiply($temp, false, $n, false)->value, 0, $n_length + 1) - if (self::_compare($result, false, $temp[self::VALUE], $temp[self::SIGN]) < 0) { - $corrector_value = self::_array_repeat(0, $n_length + 1); + if ($this->_compare($result, false, $temp[self::VALUE], $temp[self::SIGN]) < 0) { + $corrector_value = $this->_array_repeat(0, $n_length + 1); $corrector_value[count($corrector_value)] = 1; - $result = self::_add($result, false, $corrector_value, false); + $result = $this->_add($result, false, $corrector_value, false); $result = $result[self::VALUE]; } // at this point, we're subtracting a number with m.length + 1 digits from another number with m.length + 1 digits - $result = self::_subtract($result, false, $temp[self::VALUE], $temp[self::SIGN]); - while (self::_compare($result[self::VALUE], $result[self::SIGN], $n, false) > 0) { - $result = self::_subtract($result[self::VALUE], $result[self::SIGN], $n, false); + $result = $this->_subtract($result, false, $temp[self::VALUE], $temp[self::SIGN]); + while ($this->_compare($result[self::VALUE], $result[self::SIGN], $n, false) > 0) { + $result = $this->_subtract($result[self::VALUE], $result[self::SIGN], $n, false); } return $result[self::VALUE]; @@ -2131,16 +2151,16 @@ class BigInteger * * If you're going to be doing array_slice($product->value, 0, $stop), some cycles can be saved. * - * @see self::_regularBarrett() - * @param array $x_value - * @param bool $x_negative - * @param array $y_value - * @param bool $y_negative - * @param int $stop - * @return array + * @see _regularBarrett() + * @param Array $x_value + * @param Boolean $x_negative + * @param Array $y_value + * @param Boolean $y_negative + * @param Integer $stop + * @return Array * @access private */ - static function _multiplyLower($x_value, $x_negative, $y_value, $y_negative, $stop) + function _multiplyLower($x_value, $x_negative, $y_value, $y_negative, $stop) { $x_length = count($x_value); $y_length = count($y_value); @@ -2161,7 +2181,7 @@ class BigInteger $y_length = count($y_value); } - $product_value = self::_array_repeat(0, $x_length + $y_length); + $product_value = $this->_array_repeat(0, $x_length + $y_length); // the following for loop could be removed if the for loop following it // (the one with nested for loops) initially set $i to 0, but @@ -2199,7 +2219,7 @@ class BigInteger } return array( - self::VALUE => self::_trim($product_value), + self::VALUE => $this->_trim($product_value), self::SIGN => $x_negative != $y_negative ); } @@ -2212,14 +2232,14 @@ class BigInteger * improved upon (basically, by using the comba method). gcd($n, 2) must be equal to one for this function * to work correctly. * - * @see self::_prepMontgomery() - * @see self::_slidingWindow() + * @see _prepMontgomery() + * @see _slidingWindow() * @access private - * @param array $x - * @param array $n - * @return array + * @param Array $x + * @param Array $n + * @return Array */ - static function _montgomery($x, $n) + function _montgomery($x, $n) { static $cache = array( self::VARIABLE => array(), @@ -2229,7 +2249,7 @@ class BigInteger if (($key = array_search($n, $cache[self::VARIABLE])) === false) { $key = count($cache[self::VARIABLE]); $cache[self::VARIABLE][] = $x; - $cache[self::DATA][] = self::_modInverse67108864($n); + $cache[self::DATA][] = $this->_modInverse67108864($n); } $k = count($n); @@ -2239,15 +2259,15 @@ class BigInteger for ($i = 0; $i < $k; ++$i) { $temp = $result[self::VALUE][$i] * $cache[self::DATA][$key]; $temp = $temp - self::$baseFull * (self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31)); - $temp = self::_regularMultiply(array($temp), $n); + $temp = $this->_regularMultiply(array($temp), $n); $temp = array_merge($this->_array_repeat(0, $i), $temp); - $result = self::_add($result[self::VALUE], false, $temp, false); + $result = $this->_add($result[self::VALUE], false, $temp, false); } $result[self::VALUE] = array_slice($result[self::VALUE], $k); - if (self::_compare($result, false, $n, false) >= 0) { - $result = self::_subtract($result[self::VALUE], false, $n, false); + if ($this->_compare($result, false, $n, false) >= 0) { + $result = $this->_subtract($result[self::VALUE], false, $n, false); } return $result[self::VALUE]; @@ -2259,18 +2279,18 @@ class BigInteger * Interleaves the montgomery reduction and long multiplication algorithms together as described in * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=13 HAC 14.36} * - * @see self::_prepMontgomery() - * @see self::_montgomery() + * @see _prepMontgomery() + * @see _montgomery() * @access private - * @param array $x - * @param array $y - * @param array $m - * @return array + * @param Array $x + * @param Array $y + * @param Array $m + * @return Array */ - static function _montgomeryMultiply($x, $y, $m) + function _montgomeryMultiply($x, $y, $m) { - $temp = self::_multiply($x, false, $y, false); - return self::_montgomery($temp[self::VALUE], $m); + $temp = $this->_multiply($x, false, $y, false); + return $this->_montgomery($temp[self::VALUE], $m); // the following code, although not callable, can be run independently of the above code // although the above code performed better in my benchmarks the following could might @@ -2285,25 +2305,25 @@ class BigInteger if (($key = array_search($m, $cache[self::VARIABLE])) === false) { $key = count($cache[self::VARIABLE]); $cache[self::VARIABLE][] = $m; - $cache[self::DATA][] = self::_modInverse67108864($m); + $cache[self::DATA][] = $this->_modInverse67108864($m); } $n = max(count($x), count($y), count($m)); $x = array_pad($x, $n, 0); $y = array_pad($y, $n, 0); $m = array_pad($m, $n, 0); - $a = array(self::VALUE => self::_array_repeat(0, $n + 1)); + $a = array(self::VALUE => $this->_array_repeat(0, $n + 1)); for ($i = 0; $i < $n; ++$i) { $temp = $a[self::VALUE][0] + $x[$i] * $y[0]; $temp = $temp - self::$baseFull * (self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31)); $temp = $temp * $cache[self::DATA][$key]; $temp = $temp - self::$baseFull * (self::$base === 26 ? intval($temp / 0x4000000) : ($temp >> 31)); - $temp = self::_add(self::_regularMultiply(array($x[$i]), $y), false, self::_regularMultiply(array($temp), $m), false); - $a = self::_add($a[self::VALUE], false, $temp[self::VALUE], false); + $temp = $this->_add($this->_regularMultiply(array($x[$i]), $y), false, $this->_regularMultiply(array($temp), $m), false); + $a = $this->_add($a[self::VALUE], false, $temp[self::VALUE], false); $a[self::VALUE] = array_slice($a[self::VALUE], 1); } - if (self::_compare($a[self::VALUE], false, $m, false) >= 0) { - $a = self::_subtract($a[self::VALUE], false, $m, false); + if ($this->_compare($a[self::VALUE], false, $m, false) >= 0) { + $a = $this->_subtract($a[self::VALUE], false, $m, false); } return $a[self::VALUE]; } @@ -2311,17 +2331,17 @@ class BigInteger /** * Prepare a number for use in Montgomery Modular Reductions * - * @see self::_montgomery() - * @see self::_slidingWindow() + * @see _montgomery() + * @see _slidingWindow() * @access private - * @param array $x - * @param array $n - * @return array + * @param Array $x + * @param Array $n + * @return Array */ - static function _prepMontgomery($x, $n) + function _prepMontgomery($x, $n) { $lhs = new static(); - $lhs->value = array_merge(self::_array_repeat(0, count($n)), $x); + $lhs->value = array_merge($this->_array_repeat(0, count($n)), $x); $rhs = new static(); $rhs->value = $n; @@ -2350,10 +2370,10 @@ class BigInteger * * Thanks to Pedro Gimeno Fortea for input! * - * @see self::_montgomery() + * @see _montgomery() * @access private - * @param array $x - * @return int + * @param Array $x + * @return Integer */ function _modInverse67108864($x) // 2**26 == 67,108,864 { @@ -2389,18 +2409,18 @@ class BigInteger * * * @param \phpseclib\Math\BigInteger $n - * @return \phpseclib\Math\BigInteger|false + * @return mixed false, if no modular inverse exists, \phpseclib\Math\BigInteger, otherwise. * @access public * @internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=21 HAC 14.64} for more information. */ - function modInverse(BigInteger $n) + function modInverse($n) { switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: $temp = new static(); $temp->value = gmp_invert($this->value, $n->value); - return ($temp->value === false) ? false : $this->_normalize($temp); + return ( $temp->value === false ) ? false : $this->_normalize($temp); } static $zero, $one; @@ -2457,7 +2477,7 @@ class BigInteger * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=19 HAC 14.61}. As the text above 14.61 notes, * the more traditional algorithim requires "relatively costly multiple-precision divisions". */ - function extendedGCD(BigInteger $n) + function extendedGCD($n) { switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: @@ -2504,8 +2524,8 @@ class BigInteger ); } - $y = clone $n; - $x = clone $this; + $y = $n->copy(); + $x = $this->copy(); $g = new static(); $g->value = array(1); @@ -2515,8 +2535,8 @@ class BigInteger $g->_lshift(1); } - $u = clone $x; - $v = clone $y; + $u = $x->copy(); + $v = $y->copy(); $a = new static(); $b = new static(); @@ -2586,7 +2606,7 @@ class BigInteger * @return \phpseclib\Math\BigInteger * @access public */ - function gcd(BigInteger $n) + function gcd($n) { extract($this->extendedGCD($n)); return $gcd; @@ -2629,12 +2649,12 @@ class BigInteger * Note how the same comparison operator is used. If you want to test for equality, use $x->equals($y). * * @param \phpseclib\Math\BigInteger $y - * @return int < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal. + * @return Integer < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal. * @access public - * @see self::equals() + * @see equals() * @internal Could return $this->subtract($x), but that's not as fast as what we do do. */ - function compare(BigInteger $y) + function compare($y) { switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: @@ -2643,30 +2663,30 @@ class BigInteger return bccomp($this->value, $y->value, 0); } - return self::_compare($this->value, $this->is_negative, $y->value, $y->is_negative); + return $this->_compare($this->value, $this->is_negative, $y->value, $y->is_negative); } /** * Compares two numbers. * - * @param array $x_value - * @param bool $x_negative - * @param array $y_value - * @param bool $y_negative - * @return int - * @see self::compare() + * @param Array $x_value + * @param Boolean $x_negative + * @param Array $y_value + * @param Boolean $y_negative + * @return Integer + * @see compare() * @access private */ - static function _compare($x_value, $x_negative, $y_value, $y_negative) + function _compare($x_value, $x_negative, $y_value, $y_negative) { if ($x_negative != $y_negative) { - return (!$x_negative && $y_negative) ? 1 : -1; + return ( !$x_negative && $y_negative ) ? 1 : -1; } $result = $x_negative ? -1 : 1; if (count($x_value) != count($y_value)) { - return (count($x_value) > count($y_value)) ? $result : -$result; + return ( count($x_value) > count($y_value) ) ? $result : -$result; } $size = max(count($x_value), count($y_value)); @@ -2675,7 +2695,7 @@ class BigInteger for ($i = count($x_value) - 1; $i >= 0; --$i) { if ($x_value[$i] != $y_value[$i]) { - return ($x_value[$i] > $y_value[$i]) ? $result : -$result; + return ( $x_value[$i] > $y_value[$i] ) ? $result : -$result; } } @@ -2688,11 +2708,11 @@ class BigInteger * If you need to see if one number is greater than or less than another number, use BigInteger::compare() * * @param \phpseclib\Math\BigInteger $x - * @return bool + * @return Boolean * @access public - * @see self::compare() + * @see compare() */ - function equals(BigInteger $x) + function equals($x) { switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: @@ -2708,17 +2728,11 @@ class BigInteger * Some bitwise operations give different results depending on the precision being used. Examples include left * shift, not, and rotates. * - * @param int $bits + * @param Integer $bits * @access public */ function setPrecision($bits) { - if ($bits < 1) { - $this->precision = -1; - $this->bitmask = false; - - return; - } $this->precision = $bits; if (MATH_BIGINTEGER_MODE != self::MODE_BCMATH) { $this->bitmask = new static(chr((1 << ($bits & 0x7)) - 1) . str_repeat(chr(0xFF), $bits >> 3), 256); @@ -2730,18 +2744,6 @@ class BigInteger $this->value = $temp->value; } - /** - * Get Precision - * - * @return int - * @see self::setPrecision() - * @access public - */ - function getPrecision() - { - return $this->precision; - } - /** * Logical And * @@ -2750,7 +2752,7 @@ class BigInteger * @internal Implemented per a request by Lluis Pamies i Juarez * @return \phpseclib\Math\BigInteger */ - function bitwise_and(BigInteger $x) + function bitwise_and($x) { switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: @@ -2770,7 +2772,7 @@ class BigInteger return $this->_normalize(new static($left & $right, 256)); } - $result = clone $this; + $result = $this->copy(); $length = min(count($x->value), count($this->value)); @@ -2791,7 +2793,7 @@ class BigInteger * @internal Implemented per a request by Lluis Pamies i Juarez * @return \phpseclib\Math\BigInteger */ - function bitwise_or(BigInteger $x) + function bitwise_or($x) { switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: @@ -2812,7 +2814,7 @@ class BigInteger } $length = max(count($this->value), count($x->value)); - $result = clone $this; + $result = $this->copy(); $result->value = array_pad($result->value, $length, 0); $x->value = array_pad($x->value, $length, 0); @@ -2831,7 +2833,7 @@ class BigInteger * @internal Implemented per a request by Lluis Pamies i Juarez * @return \phpseclib\Math\BigInteger */ - function bitwise_xor(BigInteger $x) + function bitwise_xor($x) { switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: @@ -2852,7 +2854,7 @@ class BigInteger } $length = max(count($this->value), count($x->value)); - $result = clone $this; + $result = $this->copy(); $result->value = array_pad($result->value, $length, 0); $x->value = array_pad($x->value, $length, 0); @@ -2875,9 +2877,6 @@ class BigInteger // calculuate "not" without regard to $this->precision // (will always result in a smaller number. ie. ~1 isn't 1111 1110 - it's 0) $temp = $this->toBytes(); - if ($temp == '') { - return ''; - } $pre_msb = decbin(ord($temp[0])); $temp = ~$temp; $msb = decbin(ord($temp[0])); @@ -2895,8 +2894,7 @@ class BigInteger // generate as many leading 1's as we need to. $leading_ones = chr((1 << ($new_bits & 0x7)) - 1) . str_repeat(chr(0xFF), $new_bits >> 3); - - self::_base256_lshift($leading_ones, $current_bits); + $this->_base256_lshift($leading_ones, $current_bits); $temp = str_pad($temp, strlen($leading_ones), chr(0), STR_PAD_LEFT); @@ -2908,7 +2906,7 @@ class BigInteger * * Shifts BigInteger's by $shift bits, effectively dividing by 2**$shift. * - * @param int $shift + * @param Integer $shift * @return \phpseclib\Math\BigInteger * @access public * @internal The only version that yields any speed increases is the internal version. @@ -2946,7 +2944,7 @@ class BigInteger * * Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift. * - * @param int $shift + * @param Integer $shift * @return \phpseclib\Math\BigInteger * @access public * @internal The only version that yields any speed increases is the internal version. @@ -2984,7 +2982,7 @@ class BigInteger * * Instead of the top x bits being dropped they're appended to the shifted bit string. * - * @param int $shift + * @param Integer $shift * @return \phpseclib\Math\BigInteger * @access public */ @@ -3014,7 +3012,7 @@ class BigInteger $shift%= $precision; if (!$shift) { - return clone $this; + return $this->copy(); } $left = $this->bitwise_leftShift($shift); @@ -3029,7 +3027,7 @@ class BigInteger * * Instead of the bottom x bits being dropped they're prepended to the shifted bit string. * - * @param int $shift + * @param Integer $shift * @return \phpseclib\Math\BigInteger * @access public */ @@ -3043,11 +3041,11 @@ class BigInteger * * Byte length is equal to $length. Uses \phpseclib\Crypt\Random if it's loaded and mt_rand if it's not. * - * @param int $length + * @param Integer $length * @return \phpseclib\Math\BigInteger * @access private */ - static function _random_number_helper($size) + function _random_number_helper($size) { if (class_exists('\phpseclib\Crypt\Random')) { $random = Random::string($size); @@ -3074,16 +3072,30 @@ class BigInteger * Returns a random number between $min and $max where $min and $max * can be defined using one of the two methods: * - * BigInteger::random($min, $max) - * BigInteger::random($max, $min) + * $min->random($max) + * $max->random($min) * * @param \phpseclib\Math\BigInteger $arg1 - * @param \phpseclib\Math\BigInteger $arg2 + * @param optional \phpseclib\Math\BigInteger $arg2 * @return \phpseclib\Math\BigInteger * @access public + * @internal The API for creating random numbers used to be $a->random($min, $max), where $a was a BigInteger object. + * That method is still supported for BC purposes. */ - static function random(BigInteger $min, BigInteger $max) + function random($arg1, $arg2 = false) { + if ($arg1 === false) { + return false; + } + + if ($arg2 === false) { + $max = $arg1; + $min = $this; + } else { + $min = $arg1; + $max = $arg2; + } + $compare = $max->compare($min); if (!$compare) { @@ -3119,7 +3131,7 @@ class BigInteger http://crypto.stackexchange.com/questions/5708/creating-a-small-number-from-a-cryptographically-secure-random-string */ $random_max = new static(chr(1) . str_repeat("\0", $size), 256); - $random = static::_random_number_helper($size); + $random = $this->_random_number_helper($size); list($max_multiple) = $random_max->divide($max); $max_multiple = $max_multiple->multiply($max); @@ -3128,31 +3140,43 @@ class BigInteger $random = $random->subtract($max_multiple); $random_max = $random_max->subtract($max_multiple); $random = $random->bitwise_leftShift(8); - $random = $random->add(self::_random_number_helper(1)); + $random = $random->add($this->_random_number_helper(1)); $random_max = $random_max->bitwise_leftShift(8); list($max_multiple) = $random_max->divide($max); $max_multiple = $max_multiple->multiply($max); } list(, $random) = $random->divide($max); - return $random->add($min); + return $this->_normalize($random->add($min)); } /** * Generate a random prime number. * - * If there's not a prime within the given range, false will be returned. - * If more than $timeout seconds have elapsed, give up and return false. + * If there's not a prime within the given range, false will be returned. If more than $timeout seconds have elapsed, + * give up and return false. * - * @param \phpseclib\Math\BigInteger $min - * @param \phpseclib\Math\BigInteger $max - * @param int $timeout - * @return Math_BigInteger|false + * @param \phpseclib\Math\BigInteger $arg1 + * @param optional \phpseclib\Math\BigInteger $arg2 + * @param optional Integer $timeout + * @return Mixed * @access public * @internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap4.pdf#page=15 HAC 4.44}. */ - static function randomPrime(BigInteger $min, BigInteger $max, $timeout = false) + function randomPrime($arg1, $arg2 = false, $timeout = false) { + if ($arg1 === false) { + return false; + } + + if ($arg2 === false) { + $max = $arg1; + $min = $this; + } else { + $min = $arg1; + $max = $arg2; + } + $compare = $max->compare($min); if (!$compare) { @@ -3172,10 +3196,10 @@ class BigInteger $start = time(); - $x = self::random($min, $max); + $x = $this->random($min, $max); // gmp_nextprime() requires PHP 5 >= 5.2.0 per . - if (MATH_BIGINTEGER_MODE == self::MODE_GMP && extension_loaded('gmp')) { + if (MATH_BIGINTEGER_MODE == self::MODE_GMP && function_exists('gmp_nextprime')) { $p = new static(); $p->value = gmp_nextprime($x->value); @@ -3187,7 +3211,7 @@ class BigInteger $x = $x->subtract($one); } - return self::randomPrime($min, $x); + return $x->randomPrime($min, $x); } if ($x->equals($two)) { @@ -3200,11 +3224,11 @@ class BigInteger if ($min->equals($max)) { return false; } - $x = clone $min; + $x = $min->copy(); $x->_make_odd(); } - $initial_x = clone $x; + $initial_x = $x->copy(); while (true) { if ($timeout !== false && time() - $start > $timeout) { @@ -3218,7 +3242,7 @@ class BigInteger $x = $x->add($two); if ($x->compare($max) > 0) { - $x = clone $min; + $x = $min->copy(); if ($x->equals($two)) { return $x; } @@ -3236,7 +3260,7 @@ class BigInteger * * If the current number is odd it'll be unchanged. If it's even, one will be added to it. * - * @see self::randomPrime() + * @see randomPrime() * @access private */ function _make_odd() @@ -3262,8 +3286,8 @@ class BigInteger * $t parameter is distributability. BigInteger::randomPrime() can be distributed across multiple pageloads * on a website instead of just one. * - * @param \phpseclib\Math\BigInteger $t - * @return bool + * @param optional \phpseclib\Math\BigInteger $t + * @return Boolean * @access public * @internal Uses the * {@link http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test Miller-Rabin primality test}. See @@ -3356,18 +3380,18 @@ class BigInteger } else { $value = $this->value; foreach ($primes as $prime) { - list(, $r) = self::_divide_digit($value, $prime); + list(, $r) = $this->_divide_digit($value, $prime); if (!$r) { return count($value) == 1 && $value[0] == $prime; } } } - $n = clone $this; + $n = $this->copy(); $n_1 = $n->subtract($one); $n_2 = $n->subtract($two); - $r = clone $n_1; + $r = $n_1->copy(); $r_value = $r->value; // ie. $s = gmp_scan1($n, 0) and $r = gmp_div_q($n, gmp_pow(gmp_init('2'), $s)); if (MATH_BIGINTEGER_MODE == self::MODE_BCMATH) { @@ -3391,7 +3415,7 @@ class BigInteger } for ($i = 0; $i < $t; ++$i) { - $a = self::random($two, $n_2); + $a = $this->random($two, $n_2); $y = $a->modPow($r, $n); if (!$y->equals($one) && !$y->equals($n_1)) { @@ -3415,7 +3439,7 @@ class BigInteger * * Shifts BigInteger's by $shift bits. * - * @param int $shift + * @param Integer $shift * @access private */ function _lshift($shift) @@ -3450,7 +3474,7 @@ class BigInteger * * Shifts BigInteger's by $shift bits. * - * @param int $shift + * @param Integer $shift * @access private */ function _rshift($shift) @@ -3486,7 +3510,7 @@ class BigInteger * * @param \phpseclib\Math\BigInteger * @return \phpseclib\Math\BigInteger - * @see self::_trim() + * @see _trim() * @access private */ function _normalize($result) @@ -3496,7 +3520,7 @@ class BigInteger switch (MATH_BIGINTEGER_MODE) { case self::MODE_GMP: - if ($this->bitmask !== false) { + if (!empty($result->bitmask->value)) { $result->value = gmp_and($result->value, $result->bitmask->value); } @@ -3534,11 +3558,11 @@ class BigInteger * * Removes leading zeros * - * @param array $value + * @param Array $value * @return \phpseclib\Math\BigInteger * @access private */ - static function _trim($value) + function _trim($value) { for ($i = count($value) - 1; $i >= 0; --$i) { if ($value[$i]) { @@ -3555,10 +3579,10 @@ class BigInteger * * @param $input Array * @param $multiplier mixed - * @return array + * @return Array * @access private */ - static function _array_repeat($input, $multiplier) + function _array_repeat($input, $multiplier) { return ($multiplier) ? array_fill(0, $multiplier, $input) : array(); } @@ -3570,10 +3594,10 @@ class BigInteger * * @param $x String * @param $shift Integer - * @return string + * @return String * @access private */ - static function _base256_lshift(&$x, $shift) + function _base256_lshift(&$x, $shift) { if ($shift == 0) { return; @@ -3599,10 +3623,10 @@ class BigInteger * * @param $x String * @param $shift Integer - * @return string + * @return String * @access private */ - static function _base256_rshift(&$x, $shift) + function _base256_rshift(&$x, $shift) { if ($shift == 0) { $x = ltrim($x, chr(0)); @@ -3639,11 +3663,11 @@ class BigInteger /** * Converts 32-bit integers to bytes. * - * @param int $x - * @return string + * @param Integer $x + * @return String * @access private */ - static function _int2bytes($x) + function _int2bytes($x) { return ltrim(pack('N', $x), chr(0)); } @@ -3651,11 +3675,11 @@ class BigInteger /** * Converts bytes to 32-bit integers * - * @param string $x - * @return int + * @param String $x + * @return Integer * @access private */ - static function _bytes2int($x) + function _bytes2int($x) { $temp = unpack('Nint', str_pad($x, 4, chr(0), STR_PAD_LEFT)); return $temp['int']; @@ -3666,12 +3690,12 @@ class BigInteger * * The ability to DER-encode integers is needed to create RSA public keys for use with OpenSSL * - * @see self::modPow() + * @see modPow() * @access private - * @param int $length - * @return string + * @param Integer $length + * @return String */ - static function _encodeASN1Length($length) + function _encodeASN1Length($length) { if ($length <= 0x7F) { return chr($length); @@ -3690,11 +3714,11 @@ class BigInteger * we'll guarantee that the dividend is divisible by first subtracting the remainder. * * @access private - * @param int $x - * @param int $y - * @return int + * @param Integer $x + * @param Integer $y + * @return Integer */ - static function _safe_divide($x, $y) + function _safe_divide($x, $y) { if (self::$base === 26) { return (int) ($x / $y); diff --git a/phpseclib/Net/SCP.php b/phpseclib/Net/SCP.php index 4c28d8b0..678297e0 100644 --- a/phpseclib/Net/SCP.php +++ b/phpseclib/Net/SCP.php @@ -17,7 +17,7 @@ * exit('bad login'); * } * $scp = new \phpseclib\Net\SCP($ssh); - * + * $scp->put('abcd', str_repeat('x', 1024*1024)); * ?> * @@ -32,7 +32,8 @@ namespace phpseclib\Net; -use phpseclib\Exception\FileNotFoundException; +use phpseclib\Net\SSH1; +use phpseclib\Net\SSH2; /** * Pure-PHP implementations of SCP. @@ -53,7 +54,7 @@ class SCP const SOURCE_LOCAL_FILE = 1; /** * Reads data from a string. - */ + */ const SOURCE_STRING = 2; /**#@-*/ @@ -64,18 +65,18 @@ class SCP */ /** * SSH1 is being used. - */ + */ const MODE_SSH1 = 1; /** * SSH2 is being used. - */ + */ const MODE_SSH2 = 2; /**#@-*/ /** * SSH Object * - * @var object + * @var Object * @access private */ var $ssh; @@ -83,7 +84,7 @@ class SCP /** * Packet Size * - * @var int + * @var Integer * @access private */ var $packet_size; @@ -91,7 +92,7 @@ class SCP /** * Mode * - * @var int + * @var Integer * @access private */ var $mode; @@ -101,9 +102,9 @@ class SCP * * Connects to an SSH server * - * @param string $host - * @param int $port - * @param int $timeout + * @param String $host + * @param optional Integer $port + * @param optional Integer $timeout * @return \phpseclib\Net\SCP * @access public */ @@ -135,12 +136,11 @@ class SCP * Currently, only binary mode is supported. As such, if the line endings need to be adjusted, you will need to take * care of that, yourself. * - * @param string $remote_file - * @param string $data - * @param int $mode - * @param callable $callback - * @throws \phpseclib\Exception\FileNotFoundException if you're uploading via a file and the file doesn't exist - * @return bool + * @param String $remote_file + * @param String $data + * @param optional Integer $mode + * @param optional Callable $callback + * @return Boolean * @access public */ function put($remote_file, $data, $mode = self::SOURCE_STRING, $callback = null) @@ -168,7 +168,8 @@ class SCP $size = strlen($data); } else { if (!is_file($data)) { - throw new FileNotFoundException("$data is not a valid file"); + user_error("$data is not a valid file", E_USER_NOTICE); + return false; } $fp = @fopen($data, 'rb'); @@ -211,9 +212,9 @@ class SCP * the operation was unsuccessful. If $local_file is defined, returns true or false depending on the success of the * operation * - * @param string $remote_file - * @param string $local_file - * @return mixed + * @param String $remote_file + * @param optional String $local_file + * @return Mixed * @access public */ function get($remote_file, $local_file = false) @@ -269,7 +270,7 @@ class SCP /** * Sends a packet to an SSH server * - * @param string $data + * @param String $data * @access private */ function _send($data) @@ -287,8 +288,7 @@ class SCP /** * Receives a packet from an SSH server * - * @return string - * @throws \UnexpectedValueException on receipt of an unexpected packet + * @return String * @access private */ function _receive() @@ -314,7 +314,8 @@ class SCP $this->ssh->bitmap = 0; return false; default: - throw new \UnexpectedValueException('Unknown packet received'); + user_error('Unknown packet received', E_USER_NOTICE); + return false; } } } diff --git a/phpseclib/Net/SFTP.php b/phpseclib/Net/SFTP.php index 1729ef83..60d8923d 100644 --- a/phpseclib/Net/SFTP.php +++ b/phpseclib/Net/SFTP.php @@ -37,7 +37,7 @@ namespace phpseclib\Net; -use phpseclib\Exception\FileNotFoundException; +use phpseclib\Net\SSH2; /** * Pure-PHP implementations of SFTP. @@ -56,7 +56,7 @@ class SFTP extends SSH2 * @see \phpseclib\Net\SSH2::_send_channel_packet() * @see \phpseclib\Net\SSH2::_get_channel_packet() * @access private - */ + */ const CHANNEL = 0x100; /**#@+ @@ -65,11 +65,11 @@ class SFTP extends SSH2 */ /** * Reads data from a local file. - */ + */ const SOURCE_LOCAL_FILE = 1; /** * Reads data from a string. - */ + */ // this value isn't really used anymore but i'm keeping it reserved for historical reasons const SOURCE_STRING = 2; /** @@ -79,19 +79,19 @@ class SFTP extends SSH2 const SOURCE_CALLBACK = 16; /** * Resumes an upload - */ + */ const RESUME = 4; /** * Append a local file to an already existing remote file - */ + */ const RESUME_START = 8; /**#@-*/ /** * Packet Types * - * @see self::__construct() - * @var array + * @see \phpseclib\Net\SFTP::__construct() + * @var Array * @access private */ var $packet_types = array(); @@ -99,8 +99,8 @@ class SFTP extends SSH2 /** * Status Codes * - * @see self::__construct() - * @var array + * @see \phpseclib\Net\SFTP::__construct() + * @var Array * @access private */ var $status_codes = array(); @@ -111,8 +111,8 @@ 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 int - * @see self::_send_sftp_packet() + * @var Integer + * @see \phpseclib\Net\SFTP::_send_sftp_packet() * @access private */ var $request_id = false; @@ -123,8 +123,8 @@ 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 int - * @see self::_get_sftp_packet() + * @var Integer + * @see \phpseclib\Net\SFTP::_get_sftp_packet() * @access private */ var $packet_type = -1; @@ -132,8 +132,8 @@ class SFTP extends SSH2 /** * Packet Buffer * - * @var string - * @see self::_get_sftp_packet() + * @var String + * @see \phpseclib\Net\SFTP::_get_sftp_packet() * @access private */ var $packet_buffer = ''; @@ -141,8 +141,8 @@ class SFTP extends SSH2 /** * Extensions supported by the server * - * @var array - * @see self::_initChannel() + * @var Array + * @see \phpseclib\Net\SFTP::_initChannel() * @access private */ var $extensions = array(); @@ -150,8 +150,8 @@ class SFTP extends SSH2 /** * Server SFTP version * - * @var int - * @see self::_initChannel() + * @var Integer + * @see \phpseclib\Net\SFTP::_initChannel() * @access private */ var $version; @@ -159,9 +159,9 @@ class SFTP extends SSH2 /** * Current working directory * - * @var string - * @see self::_realpath() - * @see self::chdir() + * @var String + * @see \phpseclib\Net\SFTP::_realpath() + * @see \phpseclib\Net\SFTP::chdir() * @access private */ var $pwd = false; @@ -169,8 +169,8 @@ class SFTP extends SSH2 /** * Packet Type Log * - * @see self::getLog() - * @var array + * @see \phpseclib\Net\SFTP::getLog() + * @var Array * @access private */ var $packet_type_log = array(); @@ -178,8 +178,8 @@ class SFTP extends SSH2 /** * Packet Log * - * @see self::getLog() - * @var array + * @see \phpseclib\Net\SFTP::getLog() + * @var Array * @access private */ var $packet_log = array(); @@ -187,9 +187,9 @@ class SFTP extends SSH2 /** * Error information * - * @see self::getSFTPErrors() - * @see self::getLastSFTPError() - * @var string + * @see \phpseclib\Net\SFTP::getSFTPErrors() + * @see \phpseclib\Net\SFTP::getLastSFTPError() + * @var String * @access private */ var $sftp_errors = array(); @@ -200,10 +200,10 @@ class SFTP extends SSH2 * Rather than always having to open a directory and close it immediately there after to see if a file is a directory * we'll cache the results. * - * @see self::_update_stat_cache() - * @see self::_remove_from_stat_cache() - * @see self::_query_stat_cache() - * @var array + * @see \phpseclib\Net\SFTP::_update_stat_cache() + * @see \phpseclib\Net\SFTP::_remove_from_stat_cache() + * @see \phpseclib\Net\SFTP::_query_stat_cache() + * @var Array * @access private */ var $stat_cache = array(); @@ -211,9 +211,9 @@ class SFTP extends SSH2 /** * Max SFTP Packet Size * - * @see self::__construct() - * @see self::get() - * @var array + * @see \phpseclib\Net\SFTP::__construct() + * @see \phpseclib\Net\SFTP::get() + * @var Array * @access private */ var $max_sftp_packet; @@ -221,9 +221,9 @@ class SFTP extends SSH2 /** * Stat Cache Flag * - * @see self::disableStatCache() - * @see self::enableStatCache() - * @var bool + * @see \phpseclib\Net\SFTP::disableStatCache() + * @see \phpseclib\Net\SFTP::enableStatCache() + * @var Boolean * @access private */ var $use_stat_cache = true; @@ -231,9 +231,9 @@ class SFTP extends SSH2 /** * Sort Options * - * @see self::_comparator() - * @see self::setListOrder() - * @var array + * @see \phpseclib\Net\SFTP::_comparator() + * @see \phpseclib\Net\SFTP::setListOrder() + * @var Array * @access private */ var $sortOptions = array(); @@ -243,9 +243,9 @@ class SFTP extends SSH2 * * Connects to an SFTP server * - * @param string $host - * @param int $port - * @param int $timeout + * @param String $host + * @param optional Integer $port + * @param optional Integer $timeout * @return \phpseclib\Net\SFTP * @access public */ @@ -381,10 +381,9 @@ class SFTP extends SSH2 /** * Login * - * @param string $username - * @param string $password - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return bool + * @param String $username + * @param optional String $password + * @return Boolean * @access public */ function login($username) @@ -471,7 +470,8 @@ class SFTP extends SSH2 $response = $this->_get_sftp_packet(); if ($this->packet_type != NET_SFTP_VERSION) { - throw new \UnexpectedValueException('Expected SSH_FXP_VERSION'); + user_error('Expected SSH_FXP_VERSION'); + return false; } extract(unpack('Nversion', $this->_string_shift($response, 4))); @@ -571,7 +571,7 @@ class SFTP extends SSH2 /** * Returns the current directory name * - * @return mixed + * @return Mixed * @access public */ function pwd() @@ -582,8 +582,8 @@ class SFTP extends SSH2 /** * Logs errors * - * @param string $response - * @param int $status + * @param String $response + * @param optional Integer $status * @access public */ function _logError($response, $status = -1) @@ -608,10 +608,9 @@ class SFTP extends SSH2 * SFTP doesn't provide a mechanism by which the current working directory can be changed, so we'll emulate it. Returns * the absolute (canonicalized) path. * - * @see self::chdir() - * @param string $path - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return mixed + * @see \phpseclib\Net\SFTP::chdir() + * @param String $path + * @return Mixed * @access private */ function _realpath($path) @@ -635,7 +634,8 @@ class SFTP extends SSH2 $this->_logError($response); return false; default: - throw new \UnexpectedValueException('Expected SSH_FXP_NAME or SSH_FXP_STATUS'); + user_error('Expected SSH_FXP_NAME or SSH_FXP_STATUS'); + return false; } } @@ -665,9 +665,8 @@ class SFTP extends SSH2 /** * Changes the current directory * - * @param string $dir - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return bool + * @param String $dir + * @return Boolean * @access public */ function chdir($dir) @@ -711,7 +710,8 @@ class SFTP extends SSH2 $this->_logError($response); return false; default: - throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS'); + user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS'); + return false; } if (!$this->_close_handle($handle)) { @@ -727,9 +727,9 @@ class SFTP extends SSH2 /** * Returns a list of files in the given directory * - * @param string $dir - * @param bool $recursive - * @return mixed + * @param optional String $dir + * @param optional Boolean $recursive + * @return Mixed * @access public */ function nlist($dir = '.', $recursive = false) @@ -740,10 +740,10 @@ class SFTP extends SSH2 /** * Helper method for nlist * - * @param string $dir - * @param bool $recursive - * @param string $relativeDir - * @return mixed + * @param String $dir + * @param Boolean $recursive + * @param String $relativeDir + * @return Mixed * @access private */ function _nlist_helper($dir, $recursive, $relativeDir) @@ -776,9 +776,9 @@ class SFTP extends SSH2 /** * Returns a detailed list of files in the given directory * - * @param string $dir - * @param bool $recursive - * @return mixed + * @param optional String $dir + * @param optional Boolean $recursive + * @return Mixed * @access public */ function rawlist($dir = '.', $recursive = false) @@ -810,10 +810,9 @@ class SFTP extends SSH2 /** * Reads a list, be it detailed or not, of files in the given directory * - * @param string $dir - * @param bool $raw - * @return mixed - * @throws \UnexpectedValueException on receipt of unexpected packets + * @param String $dir + * @param optional Boolean $raw + * @return Mixed * @access private */ function _list($dir, $raw = true) @@ -845,7 +844,8 @@ class SFTP extends SSH2 $this->_logError($response); return false; default: - throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS'); + user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS'); + return false; } $this->_update_stat_cache($dir, array()); @@ -899,7 +899,8 @@ class SFTP extends SSH2 } break 2; default: - throw new \UnexpectedValueException('Expected SSH_FXP_NAME or SSH_FXP_STATUS'); + user_error('Expected SSH_FXP_NAME or SSH_FXP_STATUS'); + return false; } } @@ -919,9 +920,9 @@ class SFTP extends SSH2 * * Intended for use with uasort() * - * @param array $a - * @param array $b - * @return int + * @param Array $a + * @param Array $b + * @return Integer * @access private */ function _comparator($a, $b) @@ -1019,8 +1020,8 @@ class SFTP extends SSH2 * * Files larger than 4GB will show up as being exactly 4GB. * - * @param string $filename - * @return mixed + * @param String $filename + * @return Mixed * @access public */ function size($filename) @@ -1039,8 +1040,8 @@ class SFTP extends SSH2 /** * Save files / directories to cache * - * @param string $path - * @param mixed $value + * @param String $path + * @param Mixed $value * @access private */ function _update_stat_cache($path, $value) @@ -1083,8 +1084,8 @@ class SFTP extends SSH2 /** * Remove files / directories from cache * - * @param string $path - * @return bool + * @param String $path + * @return Boolean * @access private */ function _remove_from_stat_cache($path) @@ -1110,8 +1111,8 @@ class SFTP extends SSH2 * * Mainly used by file_exists * - * @param string $dir - * @return mixed + * @param String $dir + * @return Mixed * @access private */ function _query_stat_cache($path) @@ -1133,8 +1134,8 @@ class SFTP extends SSH2 * * Returns an array on success and false otherwise. * - * @param string $filename - * @return mixed + * @param String $filename + * @return Mixed * @access public */ function stat($filename) @@ -1190,8 +1191,8 @@ class SFTP extends SSH2 * * Returns an array on success and false otherwise. * - * @param string $filename - * @return mixed + * @param String $filename + * @return Mixed * @access public */ function lstat($filename) @@ -1256,10 +1257,9 @@ class SFTP extends SSH2 * 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 + * @param String $filename + * @param Integer $type + * @return Mixed * @access private */ function _stat($filename, $type) @@ -1279,15 +1279,16 @@ class SFTP extends SSH2 return false; } - throw new \UnexpectedValueException('Expected SSH_FXP_ATTRS or SSH_FXP_STATUS'); + user_error('Expected SSH_FXP_ATTRS or SSH_FXP_STATUS'); + return false; } /** * Truncates a file to a given length * - * @param string $filename - * @param int $new_size - * @return bool + * @param String $filename + * @param Integer $new_size + * @return Boolean * @access public */ function truncate($filename, $new_size) @@ -1302,11 +1303,10 @@ class SFTP extends SSH2 * * If the file does not exist, it will be created. * - * @param string $filename - * @param int $time - * @param int $atime - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return bool + * @param String $filename + * @param optional Integer $time + * @param optional Integer $atime + * @return Boolean * @access public */ function touch($filename, $time = null, $atime = null) @@ -1342,7 +1342,8 @@ class SFTP extends SSH2 $this->_logError($response); break; default: - throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS'); + user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS'); + return false; } return $this->_setstat($filename, $attr, false); @@ -1353,10 +1354,10 @@ class SFTP extends SSH2 * * Returns true on success or false on error. * - * @param string $filename - * @param int $uid - * @param bool $recursive - * @return bool + * @param String $filename + * @param Integer $uid + * @param optional Boolean $recursive + * @return Boolean * @access public */ function chown($filename, $uid, $recursive = false) @@ -1373,10 +1374,10 @@ class SFTP extends SSH2 * * Returns true on success or false on error. * - * @param string $filename - * @param int $gid - * @param bool $recursive - * @return bool + * @param String $filename + * @param Integer $gid + * @param optional Boolean $recursive + * @return Boolean * @access public */ function chgrp($filename, $gid, $recursive = false) @@ -1392,11 +1393,10 @@ class SFTP extends SSH2 * Returns the new file permissions on success or false on error. * If $recursive is true than this just returns true or false. * - * @param int $mode - * @param string $filename - * @param bool $recursive - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return mixed + * @param Integer $mode + * @param String $filename + * @param optional Boolean $recursive + * @return Mixed * @access public */ function chmod($mode, $filename, $recursive = false) @@ -1415,7 +1415,6 @@ class SFTP extends SSH2 return true; } - $filename = $this->_realPath($filename); // rather than return what the permissions *should* be, we'll return what they actually are. this will also // tell us if the file actually exists. // incidentally, SFTPv4+ adds an additional 32-bit integer field - flags - to the following: @@ -1434,17 +1433,17 @@ class SFTP extends SSH2 return false; } - throw new \UnexpectedValueException('Expected SSH_FXP_ATTRS or SSH_FXP_STATUS'); + user_error('Expected SSH_FXP_ATTRS or SSH_FXP_STATUS'); + return false; } /** * Sets information about a file * - * @param string $filename - * @param string $attr - * @param bool $recursive - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return bool + * @param String $filename + * @param String $attr + * @param Boolean $recursive + * @return Boolean * @access private */ function _setstat($filename, $attr, $recursive) @@ -1482,7 +1481,8 @@ class SFTP extends SSH2 */ $response = $this->_get_sftp_packet(); if ($this->packet_type != NET_SFTP_STATUS) { - throw new \UnexpectedValueException('Expected SSH_FXP_STATUS'); + user_error('Expected SSH_FXP_STATUS'); + return false; } extract(unpack('Nstatus', $this->_string_shift($response, 4))); @@ -1499,10 +1499,10 @@ class SFTP extends SSH2 * * Minimizes directory lookups and SSH_FXP_STATUS requests for speed. * - * @param string $path - * @param string $attr - * @param int $i - * @return bool + * @param String $path + * @param String $attr + * @param Integer $i + * @return Boolean * @access private */ function _setstat_recursive($path, $attr, &$i) @@ -1569,9 +1569,8 @@ class SFTP extends SSH2 /** * Return the target of a symbolic link * - * @param string $link - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return mixed + * @param String $link + * @return Mixed * @access public */ function readlink($link) @@ -1594,7 +1593,8 @@ class SFTP extends SSH2 $this->_logError($response); return false; default: - throw new \UnexpectedValueException('Expected SSH_FXP_NAME or SSH_FXP_STATUS'); + user_error('Expected SSH_FXP_NAME or SSH_FXP_STATUS'); + return false; } extract(unpack('Ncount', $this->_string_shift($response, 4))); @@ -1612,10 +1612,9 @@ class SFTP extends SSH2 * * symlink() creates a symbolic link to the existing target with the specified name link. * - * @param string $target - * @param string $link - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return bool + * @param String $target + * @param String $link + * @return Boolean * @access public */ function symlink($target, $link) @@ -1634,7 +1633,8 @@ class SFTP extends SSH2 $response = $this->_get_sftp_packet(); if ($this->packet_type != NET_SFTP_STATUS) { - throw new \UnexpectedValueException('Expected SSH_FXP_STATUS'); + user_error('Expected SSH_FXP_STATUS'); + return false; } extract(unpack('Nstatus', $this->_string_shift($response, 4))); @@ -1649,8 +1649,8 @@ class SFTP extends SSH2 /** * Creates a directory. * - * @param string $dir - * @return bool + * @param String $dir + * @return Boolean * @access public */ function mkdir($dir, $mode = -1, $recursive = false) @@ -1684,9 +1684,8 @@ class SFTP extends SSH2 /** * Helper function for directory creation * - * @param string $dir - * @return bool - * @throws \UnexpectedValueException on receipt of unexpected packets + * @param String $dir + * @return Boolean * @access private */ function _mkdir_helper($dir, $attr) @@ -1697,7 +1696,8 @@ class SFTP extends SSH2 $response = $this->_get_sftp_packet(); if ($this->packet_type != NET_SFTP_STATUS) { - throw new \UnexpectedValueException('Expected SSH_FXP_STATUS'); + user_error('Expected SSH_FXP_STATUS'); + return false; } extract(unpack('Nstatus', $this->_string_shift($response, 4))); @@ -1712,9 +1712,8 @@ class SFTP extends SSH2 /** * Removes a directory. * - * @param string $dir - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return bool + * @param String $dir + * @return Boolean * @access public */ function rmdir($dir) @@ -1734,7 +1733,8 @@ class SFTP extends SSH2 $response = $this->_get_sftp_packet(); if ($this->packet_type != NET_SFTP_STATUS) { - throw new \UnexpectedValueException('Expected SSH_FXP_STATUS'); + user_error('Expected SSH_FXP_STATUS'); + return false; } extract(unpack('Nstatus', $this->_string_shift($response, 4))); @@ -1788,16 +1788,13 @@ class SFTP extends SSH2 * * Setting $local_start to > 0 or $mode | self::RESUME_START doesn't do anything unless $mode | self::SOURCE_LOCAL_FILE. * - * @param string $remote_file - * @param string|resource $data - * @param int $mode - * @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 + * @param String $remote_file + * @param String|resource $data + * @param optional Integer $mode + * @param optional Integer $start + * @param optional Integer $local_start + * @param optional callable|null $progressCallback + * @return Boolean * @access public * @internal ASCII mode for SFTPv4/5/6 can be supported by adding a new function - \phpseclib\Net\SFTP::setMode(). */ @@ -1844,7 +1841,8 @@ class SFTP extends SSH2 $this->_logError($response); return false; default: - throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS'); + user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS'); + return false; } // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.3 @@ -1852,7 +1850,7 @@ class SFTP extends SSH2 switch (true) { case $mode & self::SOURCE_CALLBACK: if (!is_callable($data)) { - throw new \BadFunctionCallException("\$data should be is_callable() if you specify SOURCE_CALLBACK flag"); + user_error("\$data should be is_callable() if you specify SOURCE_CALLBACK flag"); } $dataCallback = $data; // do nothing @@ -1863,7 +1861,8 @@ class SFTP extends SSH2 break; case $mode & self::SOURCE_LOCAL_FILE: if (!is_file($data)) { - throw new FileNotFoundException("$data is not a valid file"); + user_error("$data is not a valid file"); + return false; } $fp = @fopen($data, 'rb'); if (!$fp) { @@ -1877,7 +1876,10 @@ class SFTP extends SSH2 if ($local_start >= 0) { fseek($fp, $local_start); - $size-= $local_start; + } elseif ($mode & self::RESUME_START) { + // do nothing + } else { + fseek($fp, $offset); } } elseif ($dataCallback) { $size = 0; @@ -1946,9 +1948,8 @@ class SFTP extends SSH2 * Sending an SSH_FXP_WRITE packet and immediately reading its response isn't as efficient as blindly sending out $i * SSH_FXP_WRITEs, in succession, and then reading $i responses. * - * @param int $i - * @return bool - * @throws \UnexpectedValueException on receipt of unexpected packets + * @param Integer $i + * @return Boolean * @access private */ function _read_put_responses($i) @@ -1956,7 +1957,8 @@ class SFTP extends SSH2 while ($i--) { $response = $this->_get_sftp_packet(); if ($this->packet_type != NET_SFTP_STATUS) { - throw new \UnexpectedValueException('Expected SSH_FXP_STATUS'); + user_error('Expected SSH_FXP_STATUS'); + return false; } extract(unpack('Nstatus', $this->_string_shift($response, 4))); @@ -1972,9 +1974,8 @@ class SFTP extends SSH2 /** * Close handle * - * @param string $handle - * @return bool - * @throws \UnexpectedValueException on receipt of unexpected packets + * @param String $handle + * @return Boolean * @access private */ function _close_handle($handle) @@ -1987,7 +1988,8 @@ 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) { - throw new \UnexpectedValueException('Expected SSH_FXP_STATUS'); + user_error('Expected SSH_FXP_STATUS'); + return false; } extract(unpack('Nstatus', $this->_string_shift($response, 4))); @@ -2008,12 +2010,11 @@ class SFTP extends SSH2 * * $offset and $length can be used to download files in chunks. * - * @param string $remote_file - * @param string $local_file - * @param int $offset - * @param int $length - * @throws \UnexpectedValueException on receipt of unexpected packets - * @return mixed + * @param String $remote_file + * @param optional String $local_file + * @param optional Integer $offset + * @param optional Integer $length + * @return Mixed * @access public */ function get($remote_file, $local_file = false, $offset = 0, $length = -1) @@ -2041,7 +2042,8 @@ class SFTP extends SSH2 $this->_logError($response); return false; default: - throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS'); + user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS'); + return false; } if (is_resource($local_file)) { @@ -2063,68 +2065,40 @@ class SFTP extends SSH2 $fclose_check = $local_file !== false && !is_resource($local_file); $start = $offset; - $read = 0; + $size = $this->max_sftp_packet < $length || $length < 0 ? $this->max_sftp_packet : $length; while (true) { - $i = 0; + $packet = pack('Na*N3', strlen($handle), $handle, $offset / 4294967296, $offset, $size); + if (!$this->_send_sftp_packet(NET_SFTP_READ, $packet)) { + if ($fclose_check) { + fclose($fp); + } + return false; + } - while ($i < NET_SFTP_QUEUE_SIZE && ($length < 0 || $read < $length)) { - $tempoffset = $start + $read; - - $packet_size = $length > 0 ? min($this->max_sftp_packet, $length - $read) : $this->max_sftp_packet; - - $packet = pack('Na*N3', strlen($handle), $handle, $tempoffset / 4294967296, $tempoffset, $packet_size); - if (!$this->_send_sftp_packet(NET_SFTP_READ, $packet)) { + $response = $this->_get_sftp_packet(); + switch ($this->packet_type) { + case NET_SFTP_DATA: + $temp = substr($response, 4); + $offset+= strlen($temp); + if ($local_file === false) { + $content.= $temp; + } else { + fputs($fp, $temp); + } + break; + case NET_SFTP_STATUS: + // could, in theory, return false if !strlen($content) but we'll hold off for the time being + $this->_logError($response); + break 2; + default: + user_error('Expected SSH_FXP_DATA or SSH_FXP_STATUS'); if ($fclose_check) { fclose($fp); } return false; - } - $packet = null; - $read+= $packet_size; - $i++; } - if (!$i) { - break; - } - - $clear_responses = false; - while ($i > 0) { - $i--; - - if ($clear_responses) { - $this->_get_sftp_packet(); - continue; - } else { - $response = $this->_get_sftp_packet(); - } - - switch ($this->packet_type) { - case NET_SFTP_DATA: - $temp = substr($response, 4); - $offset+= strlen($temp); - if ($local_file === false) { - $content.= $temp; - } else { - fputs($fp, $temp); - } - $temp = null; - break; - case NET_SFTP_STATUS: - // could, in theory, return false if !strlen($content) but we'll hold off for the time being - $this->_logError($response); - $clear_responses = true; // don't break out of the loop yet, so we can read the remaining responses - break; - default: - if ($fclose_check) { - fclose($fp); - } - throw new \UnexpectedValueException('Expected SSH_FXP_DATA or SSH_FXP_STATUS'); - } - $response = null; - } - - if ($clear_responses) { + if ($length > 0 && $length <= $offset - $start) { break; } } @@ -2152,10 +2126,9 @@ class SFTP extends SSH2 /** * Deletes a file on the SFTP server. * - * @param string $path - * @param bool $recursive - * @return bool - * @throws \UnexpectedValueException on receipt of unexpected packets + * @param String $path + * @param Boolean $recursive + * @return Boolean * @access public */ function delete($path, $recursive = true) @@ -2176,7 +2149,8 @@ class SFTP extends SSH2 $response = $this->_get_sftp_packet(); if ($this->packet_type != NET_SFTP_STATUS) { - throw new \UnexpectedValueException('Expected SSH_FXP_STATUS'); + user_error('Expected SSH_FXP_STATUS'); + return false; } // if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED @@ -2202,9 +2176,9 @@ class SFTP extends SSH2 * * Minimizes directory lookups and SSH_FXP_STATUS requests for speed. * - * @param string $path - * @param int $i - * @return bool + * @param String $path + * @param Integer $i + * @return Boolean * @access private */ function _delete_recursive($path, &$i) @@ -2269,8 +2243,8 @@ class SFTP extends SSH2 /** * Checks whether a file or directory exists * - * @param string $path - * @return bool + * @param String $path + * @return Boolean * @access public */ function file_exists($path) @@ -2292,8 +2266,8 @@ class SFTP extends SSH2 /** * Tells whether the filename is a directory * - * @param string $path - * @return bool + * @param String $path + * @return Boolean * @access public */ function is_dir($path) @@ -2308,8 +2282,8 @@ class SFTP extends SSH2 /** * Tells whether the filename is a regular file * - * @param string $path - * @return bool + * @param String $path + * @return Boolean * @access public */ function is_file($path) @@ -2324,8 +2298,8 @@ class SFTP extends SSH2 /** * Tells whether the filename is a symbolic link * - * @param string $path - * @return bool + * @param String $path + * @return Boolean * @access public */ function is_link($path) @@ -2340,8 +2314,8 @@ class SFTP extends SSH2 /** * Gets last access time of file * - * @param string $path - * @return mixed + * @param String $path + * @return Mixed * @access public */ function fileatime($path) @@ -2352,8 +2326,8 @@ class SFTP extends SSH2 /** * Gets file modification time * - * @param string $path - * @return mixed + * @param String $path + * @return Mixed * @access public */ function filemtime($path) @@ -2364,8 +2338,8 @@ class SFTP extends SSH2 /** * Gets file permissions * - * @param string $path - * @return mixed + * @param String $path + * @return Mixed * @access public */ function fileperms($path) @@ -2376,8 +2350,8 @@ class SFTP extends SSH2 /** * Gets file owner * - * @param string $path - * @return mixed + * @param String $path + * @return Mixed * @access public */ function fileowner($path) @@ -2388,8 +2362,8 @@ class SFTP extends SSH2 /** * Gets file group * - * @param string $path - * @return mixed + * @param String $path + * @return Mixed * @access public */ function filegroup($path) @@ -2400,8 +2374,8 @@ class SFTP extends SSH2 /** * Gets file size * - * @param string $path - * @return mixed + * @param String $path + * @return Mixed * @access public */ function filesize($path) @@ -2412,8 +2386,8 @@ class SFTP extends SSH2 /** * Gets file type * - * @param string $path - * @return mixed + * @param String $path + * @return Mixed * @access public */ function filetype($path) @@ -2446,9 +2420,9 @@ class SFTP extends SSH2 * * Uses cache if appropriate. * - * @param string $path - * @param string $prop - * @return mixed + * @param String $path + * @param String $prop + * @return Mixed * @access private */ function _get_stat_cache_prop($path, $prop) @@ -2461,9 +2435,9 @@ class SFTP extends SSH2 * * Uses cache if appropriate. * - * @param string $path - * @param string $prop - * @return mixed + * @param String $path + * @param String $prop + * @return Mixed * @access private */ function _get_lstat_cache_prop($path, $prop) @@ -2476,9 +2450,9 @@ class SFTP extends SSH2 * * Uses cache if appropriate. * - * @param string $path - * @param string $prop - * @return mixed + * @param String $path + * @param String $prop + * @return Mixed * @access private */ function _get_xstat_cache_prop($path, $prop, $type) @@ -2505,10 +2479,9 @@ class SFTP extends SSH2 /** * Renames a file or a directory on the SFTP server * - * @param string $oldname - * @param string $newname - * @return bool - * @throws \UnexpectedValueException on receipt of unexpected packets + * @param String $oldname + * @param String $newname + * @return Boolean * @access public */ function rename($oldname, $newname) @@ -2531,7 +2504,8 @@ class SFTP extends SSH2 $response = $this->_get_sftp_packet(); if ($this->packet_type != NET_SFTP_STATUS) { - throw new \UnexpectedValueException('Expected SSH_FXP_STATUS'); + user_error('Expected SSH_FXP_STATUS'); + return false; } // if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED @@ -2555,8 +2529,8 @@ class SFTP extends SSH2 * * See '7. File Attributes' of draft-ietf-secsh-filexfer-13 for more info. * - * @param string $response - * @return array + * @param String $response + * @return Array * @access private */ function _parseAttributes(&$response) @@ -2609,8 +2583,8 @@ class SFTP extends SSH2 * * Quoting the SFTP RFC, "Implementations MUST NOT send bits that are not defined" but they seem to anyway * - * @param int $mode - * @return int + * @param Integer $mode + * @return Integer * @access private */ function _parseMode($mode) @@ -2656,8 +2630,8 @@ class SFTP extends SSH2 * * If the longname is in an unrecognized format bool(false) is returned. * - * @param string $longname - * @return mixed + * @param String $longname + * @return Mixed * @access private */ function _parseLongname($longname) @@ -2685,11 +2659,11 @@ class SFTP extends SSH2 * * See '6. General Packet Format' of draft-ietf-secsh-filexfer-13 for more info. * - * @param int $type - * @param string $data - * @see self::_get_sftp_packet() - * @see self::_send_channel_packet() - * @return bool + * @param Integer $type + * @param String $data + * @see \phpseclib\Net\SFTP::_get_sftp_packet() + * @see \phpseclib\Net\SSH2::_send_channel_packet() + * @return Boolean * @access private */ function _send_sftp_packet($type, $data) @@ -2729,8 +2703,8 @@ class SFTP extends SSH2 * There can be one SSH_MSG_CHANNEL_DATA messages containing two SFTP packets or there can be two SSH_MSG_CHANNEL_DATA * messages containing one SFTP packet. * - * @see self::_send_sftp_packet() - * @return string + * @see \phpseclib\Net\SFTP::_send_sftp_packet() + * @return String * @access private */ function _get_sftp_packet() @@ -2802,7 +2776,7 @@ class SFTP extends SSH2 * Returns a string if NET_SFTP_LOGGING == NET_SFTP_LOG_COMPLEX, an array if NET_SFTP_LOGGING == NET_SFTP_LOG_SIMPLE and false if !defined('NET_SFTP_LOGGING') * * @access public - * @return string or Array + * @return String or Array */ function getSFTPLog() { @@ -2823,7 +2797,7 @@ class SFTP extends SSH2 /** * Returns all errors * - * @return string + * @return String * @access public */ function getSFTPErrors() @@ -2834,7 +2808,7 @@ class SFTP extends SSH2 /** * Returns the last error * - * @return string + * @return String * @access public */ function getLastSFTPError() @@ -2845,7 +2819,7 @@ class SFTP extends SSH2 /** * Get supported SFTP versions * - * @return array + * @return Array * @access public */ function getSupportedVersions() @@ -2860,8 +2834,8 @@ class SFTP extends SSH2 /** * Disconnect * - * @param int $reason - * @return bool + * @param Integer $reason + * @return Boolean * @access private */ function _disconnect($reason) diff --git a/phpseclib/Net/SFTP/Stream.php b/phpseclib/Net/SFTP/Stream.php index d19d08b8..2758e73c 100644 --- a/phpseclib/Net/SFTP/Stream.php +++ b/phpseclib/Net/SFTP/Stream.php @@ -19,7 +19,6 @@ namespace phpseclib\Net\SFTP; use phpseclib\Crypt\RSA; use phpseclib\Net\SFTP; -use phpseclib\Net\SSH2; /** * SFTP Stream Wrapper @@ -35,14 +34,14 @@ class Stream * * Rather than re-create the connection we re-use instances if possible * - * @var array + * @var Array */ static $instances; /** * SFTP instance * - * @var object + * @var Object * @access private */ var $sftp; @@ -50,7 +49,7 @@ class Stream /** * Path * - * @var string + * @var String * @access private */ var $path; @@ -58,7 +57,7 @@ class Stream /** * Mode * - * @var string + * @var String * @access private */ var $mode; @@ -66,7 +65,7 @@ class Stream /** * Position * - * @var int + * @var Integer * @access private */ var $pos; @@ -74,7 +73,7 @@ class Stream /** * Size * - * @var int + * @var Integer * @access private */ var $size; @@ -82,7 +81,7 @@ class Stream /** * Directory entries * - * @var array + * @var Array * @access private */ var $entries; @@ -90,7 +89,7 @@ class Stream /** * EOF flag * - * @var bool + * @var Boolean * @access private */ var $eof; @@ -100,7 +99,7 @@ class Stream * * Technically this needs to be publically accessible so PHP can set it directly * - * @var resource + * @var Resource * @access public */ var $context; @@ -108,7 +107,7 @@ class Stream /** * Notification callback function * - * @var callable + * @var Callable * @access public */ var $notification; @@ -116,8 +115,8 @@ class Stream /** * Registers this class as a URL wrapper. * - * @param string $protocol The wrapper name to be registered. - * @return bool True on success, false otherwise. + * @param optional String $protocol The wrapper name to be registered. + * @return Boolean True on success, false otherwise. * @access public */ static function register($protocol = 'sftp') @@ -148,24 +147,13 @@ class Stream * If "notification" is set as a context parameter the message code for successful login is * NET_SSH2_MSG_USERAUTH_SUCCESS. For a failed login it's NET_SSH2_MSG_USERAUTH_FAILURE. * - * @param string $path - * @return string + * @param String $path + * @return String * @access private */ function _parse_path($path) { - $orig = $path; extract(parse_url($path) + array('port' => 22)); - if (isset($query)) { - $path.= '?' . $query; - } elseif (preg_match('/(\?|\?#)$/', $orig)) { - $path.= '?'; - } - if (isset($fragment)) { - $path.= '#' . $fragment; - } elseif ($orig[strlen($orig) - 1] == '#') { - $path.= '#'; - } if (!isset($host)) { return false; @@ -178,12 +166,13 @@ class Stream } } - if (preg_match('/^{[a-z0-9]+}$/i', $host)) { - $host = SSH2::getConnectionByResourceId($host); - if ($host === false) { + if ($host[0] == '$') { + $host = substr($host, 1); + global $$host; + if (($$host instanceof SFTP) === false) { return false; } - $this->sftp = $host; + $this->sftp = $$host; } else { if (isset($this->context)) { $context = stream_context_get_options($this->context); @@ -250,11 +239,11 @@ class Stream /** * Opens file or URL * - * @param string $path - * @param string $mode - * @param int $options - * @param string $opened_path - * @return bool + * @param String $path + * @param String $mode + * @param Integer $options + * @param String $opened_path + * @return Boolean * @access public */ function _stream_open($path, $mode, $options, &$opened_path) @@ -295,8 +284,8 @@ class Stream /** * Read from stream * - * @param int $count - * @return mixed + * @param Integer $count + * @return Mixed * @access public */ function _stream_read($count) @@ -337,8 +326,8 @@ class Stream /** * Write to stream * - * @param string $data - * @return mixed + * @param String $data + * @return Mixed * @access public */ function _stream_write($data) @@ -372,7 +361,7 @@ class Stream /** * Retrieve the current position of a stream * - * @return int + * @return Integer * @access public */ function _stream_tell() @@ -390,7 +379,7 @@ class Stream * will return false. do fread($fp, 1) and feof() will then return true. do fseek($fp, 10) on ablank file and feof() * will return false. do fread($fp, 1) and feof() will then return true. * - * @return bool + * @return Boolean * @access public */ function _stream_eof() @@ -401,9 +390,9 @@ class Stream /** * Seeks to specific location in a stream * - * @param int $offset - * @param int $whence - * @return bool + * @param Integer $offset + * @param Integer $whence + * @return Boolean * @access public */ function _stream_seek($offset, $whence) @@ -429,10 +418,10 @@ class Stream /** * Change stream options * - * @param string $path - * @param int $option - * @param mixed $var - * @return bool + * @param String $path + * @param Integer $option + * @param Mixed $var + * @return Boolean * @access public */ function _stream_metadata($path, $option, $var) @@ -463,8 +452,8 @@ class Stream /** * Retrieve the underlaying resource * - * @param int $cast_as - * @return resource + * @param Integer $cast_as + * @return Resource * @access public */ function _stream_cast($cast_as) @@ -475,8 +464,8 @@ class Stream /** * Advisory file locking * - * @param int $operation - * @return bool + * @param Integer $operation + * @return Boolean * @access public */ function _stream_lock($operation) @@ -491,9 +480,9 @@ class Stream * If newname exists, it will be overwritten. This is a departure from what \phpseclib\Net\SFTP * does. * - * @param string $path_from - * @param string $path_to - * @return bool + * @param String $path_from + * @param String $path_to + * @return Boolean * @access public */ function _rename($path_from, $path_to) @@ -543,9 +532,9 @@ class Stream * string longname * ATTRS attrs * - * @param string $path - * @param int $options - * @return bool + * @param String $path + * @param Integer $options + * @return Boolean * @access public */ function _dir_opendir($path, $options) @@ -562,7 +551,7 @@ class Stream /** * Read entry from directory handle * - * @return mixed + * @return Mixed * @access public */ function _dir_readdir() @@ -576,7 +565,7 @@ class Stream /** * Rewind directory handle * - * @return bool + * @return Boolean * @access public */ function _dir_rewinddir() @@ -588,7 +577,7 @@ class Stream /** * Close directory handle * - * @return bool + * @return Boolean * @access public */ function _dir_closedir() @@ -601,10 +590,10 @@ class Stream * * Only valid $options is STREAM_MKDIR_RECURSIVE * - * @param string $path - * @param int $mode - * @param int $options - * @return bool + * @param String $path + * @param Integer $mode + * @param Integer $options + * @return Boolean * @access public */ function _mkdir($path, $mode, $options) @@ -625,10 +614,10 @@ class Stream * STREAM_MKDIR_RECURSIVE is supposed to be set. Also, when I try it out with rmdir() I get 8 as * $options. What does 8 correspond to? * - * @param string $path - * @param int $mode - * @param int $options - * @return bool + * @param String $path + * @param Integer $mode + * @param Integer $options + * @return Boolean * @access public */ function _rmdir($path, $options) @@ -646,7 +635,7 @@ class Stream * * See . Always returns true because \phpseclib\Net\SFTP doesn't cache stuff before writing * - * @return bool + * @return Boolean * @access public */ function _stream_flush() @@ -657,7 +646,7 @@ class Stream /** * Retrieve information about a file resource * - * @return mixed + * @return Mixed * @access public */ function _stream_stat() @@ -672,8 +661,8 @@ class Stream /** * Delete a file * - * @param string $path - * @return bool + * @param String $path + * @return Boolean * @access public */ function _unlink($path) @@ -693,9 +682,9 @@ class Stream * might be worthwhile to reconstruct bits 12-16 (ie. the file type) if mode doesn't have them but we'll * cross that bridge when and if it's reached * - * @param string $path - * @param int $flags - * @return mixed + * @param String $path + * @param Integer $flags + * @return Mixed * @access public */ function _url_stat($path, $flags) @@ -716,8 +705,8 @@ class Stream /** * Truncate stream * - * @param int $new_size - * @return bool + * @param Integer $new_size + * @return Boolean * @access public */ function _stream_truncate($new_size) @@ -738,10 +727,10 @@ class Stream * STREAM_OPTION_WRITE_BUFFER isn't supported for the same reason stream_flush isn't. * The other two aren't supported because of limitations in \phpseclib\Net\SFTP. * - * @param int $option - * @param int $arg1 - * @param int $arg2 - * @return bool + * @param Integer $option + * @param Integer $arg1 + * @param Integer $arg2 + * @return Boolean * @access public */ function _stream_set_option($option, $arg1, $arg2) @@ -768,9 +757,9 @@ class Stream * If NET_SFTP_STREAM_LOGGING is defined all calls will be output on the screen and then (regardless of whether or not * NET_SFTP_STREAM_LOGGING is enabled) the parameters will be passed through to the appropriate method. * - * @param string - * @param array - * @return mixed + * @param String + * @param Array + * @return Mixed * @access public */ function __call($name, $arguments) diff --git a/phpseclib/Net/SSH1.php b/phpseclib/Net/SSH1.php index 2a8c1d8d..918c791e 100644 --- a/phpseclib/Net/SSH1.php +++ b/phpseclib/Net/SSH1.php @@ -78,24 +78,24 @@ class SSH1 * IDEA in CFB mode * * Not supported. - */ + */ const CIPHER_IDEA = 1; /** * DES in CBC mode - */ + */ const CIPHER_DES = 2; /** * Triple-DES in CBC mode * * All implementations are required to support this - */ + */ const CIPHER_3DES = 3; /** * TRI's Simple Stream encryption CBC * * Not supported nor is it defined in the official SSH1 specs. OpenSSH, however, does define it (see cipher.h), * although it doesn't use it (see cipher.c) - */ + */ const CIPHER_BROKEN_TSS = 4; /** * RC4 @@ -111,14 +111,14 @@ class SSH1 * * This library currently only supports encryption when the same key is being used for both directions. This is * because there's only one $crypto object. Two could be added ($encrypt and $decrypt, perhaps). - */ + */ const CIPHER_RC4 = 5; /** * Blowfish * * Not supported nor is it defined in the official SSH1 specs. OpenSSH, however, defines it (see cipher.h) and * uses it (see cipher.c) - */ + */ const CIPHER_BLOWFISH = 6; /**#@-*/ @@ -130,21 +130,21 @@ class SSH1 */ /** * .rhosts or /etc/hosts.equiv - */ + */ const AUTH_RHOSTS = 1; /** * pure RSA authentication - */ + */ const AUTH_RSA = 2; /** * password authentication * * This is the only method that is supported by this library. - */ + */ const AUTH_PASSWORD = 3; /** * .rhosts with RSA host authentication - */ + */ const AUTH_RHOSTS_RSA = 4; /**#@-*/ @@ -162,7 +162,7 @@ class SSH1 * * @see \phpseclib\Net\SSH1::_get_binary_packet() * @access private - */ + */ const RESPONSE_TYPE = 1; /** @@ -170,7 +170,7 @@ class SSH1 * * @see \phpseclib\Net\SSH1::_get_binary_packet() * @access private - */ + */ const RESPONSE_DATA = 2; /**#@+ @@ -191,19 +191,19 @@ class SSH1 */ /** * Returns the message numbers - */ + */ const LOG_SIMPLE = 1; /** * Returns the message content - */ + */ const LOG_COMPLEX = 2; /** * Outputs the content real-time - */ + */ const LOG_REALTIME = 3; /** * Dumps the content real-time to a file - */ + */ const LOG_REALTIME_FILE = 4; /**#@-*/ @@ -213,18 +213,18 @@ class SSH1 */ /** * Returns when a string matching $expect exactly is found - */ + */ const READ_SIMPLE = 1; /** * Returns when a string matching the regular expression $expect is found - */ + */ const READ_REGEX = 2; /**#@-*/ /** * The SSH identifier * - * @var string + * @var String * @access private */ var $identifier = 'SSH-1.5-phpseclib'; @@ -232,7 +232,7 @@ class SSH1 /** * The Socket Object * - * @var object + * @var Object * @access private */ var $fsock; @@ -240,7 +240,7 @@ class SSH1 /** * The cryptography object * - * @var object + * @var Object * @access private */ var $crypto = false; @@ -251,7 +251,7 @@ class SSH1 * The bits that are set represent functions that have been called already. This is used to determine * if a requisite function has been successfully executed. If not, an error should be thrown. * - * @var int + * @var Integer * @access private */ var $bitmap = 0; @@ -261,8 +261,8 @@ class SSH1 * * Logged for debug purposes * - * @see self::getServerKeyPublicExponent() - * @var string + * @see \phpseclib\Net\SSH1::getServerKeyPublicExponent() + * @var String * @access private */ var $server_key_public_exponent; @@ -272,8 +272,8 @@ class SSH1 * * Logged for debug purposes * - * @see self::getServerKeyPublicModulus() - * @var string + * @see \phpseclib\Net\SSH1::getServerKeyPublicModulus() + * @var String * @access private */ var $server_key_public_modulus; @@ -283,8 +283,8 @@ class SSH1 * * Logged for debug purposes * - * @see self::getHostKeyPublicExponent() - * @var string + * @see \phpseclib\Net\SSH1::getHostKeyPublicExponent() + * @var String * @access private */ var $host_key_public_exponent; @@ -294,8 +294,8 @@ class SSH1 * * Logged for debug purposes * - * @see self::getHostKeyPublicModulus() - * @var string + * @see \phpseclib\Net\SSH1::getHostKeyPublicModulus() + * @var String * @access private */ var $host_key_public_modulus; @@ -305,8 +305,8 @@ class SSH1 * * Logged for debug purposes * - * @see self::getSupportedCiphers() - * @var array + * @see \phpseclib\Net\SSH1::getSupportedCiphers() + * @var Array * @access private */ var $supported_ciphers = array( @@ -324,8 +324,8 @@ class SSH1 * * Logged for debug purposes * - * @see self::getSupportedAuthentications() - * @var array + * @see \phpseclib\Net\SSH1::getSupportedAuthentications() + * @var Array * @access private */ var $supported_authentications = array( @@ -338,8 +338,8 @@ class SSH1 /** * Server Identification * - * @see self::getServerIdentification() - * @var string + * @see \phpseclib\Net\SSH1::getServerIdentification() + * @var String * @access private */ var $server_identification = ''; @@ -347,8 +347,8 @@ class SSH1 /** * Protocol Flags * - * @see self::__construct() - * @var array + * @see \phpseclib\Net\SSH1::__construct() + * @var Array * @access private */ var $protocol_flags = array(); @@ -356,8 +356,8 @@ class SSH1 /** * Protocol Flag Log * - * @see self::getLog() - * @var array + * @see \phpseclib\Net\SSH1::getLog() + * @var Array * @access private */ var $protocol_flag_log = array(); @@ -365,8 +365,8 @@ class SSH1 /** * Message Log * - * @see self::getLog() - * @var array + * @see \phpseclib\Net\SSH1::getLog() + * @var Array * @access private */ var $message_log = array(); @@ -374,8 +374,8 @@ class SSH1 /** * Real-time log file pointer * - * @see self::_append_log() - * @var resource + * @see \phpseclib\Net\SSH1::_append_log() + * @var Resource * @access private */ var $realtime_log_file; @@ -383,8 +383,8 @@ class SSH1 /** * Real-time log file size * - * @see self::_append_log() - * @var int + * @see \phpseclib\Net\SSH1::_append_log() + * @var Integer * @access private */ var $realtime_log_size; @@ -392,8 +392,8 @@ class SSH1 /** * Real-time log file wrap boolean * - * @see self::_append_log() - * @var bool + * @see \phpseclib\Net\SSH1::_append_log() + * @var Boolean * @access private */ var $realtime_log_wrap; @@ -401,8 +401,8 @@ class SSH1 /** * Interactive Buffer * - * @see self::read() - * @var array + * @see \phpseclib\Net\SSH1::read() + * @var Array * @access private */ var $interactiveBuffer = ''; @@ -410,7 +410,7 @@ class SSH1 /** * Timeout * - * @see self::setTimeout() + * @see \phpseclib\Net\SSH1::setTimeout() * @access private */ var $timeout; @@ -418,7 +418,7 @@ class SSH1 /** * Current Timeout * - * @see self::_get_channel_packet() + * @see \phpseclib\Net\SSH1::_get_channel_packet() * @access private */ var $curTimeout; @@ -426,7 +426,7 @@ class SSH1 /** * Log Boundary * - * @see self::_format_log() + * @see \phpseclib\Net\SSH1::_format_log * @access private */ var $log_boundary = ':'; @@ -434,7 +434,7 @@ class SSH1 /** * Log Long Width * - * @see self::_format_log() + * @see \phpseclib\Net\SSH1::_format_log * @access private */ var $log_long_width = 65; @@ -442,7 +442,7 @@ class SSH1 /** * Log Short Width * - * @see self::_format_log() + * @see \phpseclib\Net\SSH1::_format_log * @access private */ var $log_short_width = 16; @@ -450,9 +450,9 @@ class SSH1 /** * Hostname * - * @see self::__construct() - * @see self::_connect() - * @var string + * @see \phpseclib\Net\SSH1::__construct() + * @see \phpseclib\Net\SSH1::_connect() + * @var String * @access private */ var $host; @@ -460,9 +460,9 @@ class SSH1 /** * Port Number * - * @see self::__construct() - * @see self::_connect() - * @var int + * @see \phpseclib\Net\SSH1::__construct() + * @see \phpseclib\Net\SSH1::_connect() + * @var Integer * @access private */ var $port; @@ -475,9 +475,9 @@ class SSH1 * however, is non-optional. There will be a timeout, whether or not you set it. If you don't it'll be * 10 seconds. It is used by fsockopen() in that function. * - * @see self::__construct() - * @see self::_connect() - * @var int + * @see \phpseclib\Net\SSH1::__construct() + * @see \phpseclib\Net\SSH1::_connect() + * @var Integer * @access private */ var $connectionTimeout; @@ -485,9 +485,9 @@ class SSH1 /** * Default cipher * - * @see self::__construct() - * @see self::_connect() - * @var int + * @see \phpseclib\Net\SSH1::__construct() + * @see \phpseclib\Net\SSH1::_connect() + * @var Integer * @access private */ var $cipher; @@ -497,10 +497,10 @@ class SSH1 * * Connects to an SSHv1 server * - * @param string $host - * @param int $port - * @param int $timeout - * @param int $cipher + * @param String $host + * @param optional Integer $port + * @param optional Integer $timeout + * @param optional Integer $cipher * @return \phpseclib\Net\SSH1 * @access public */ @@ -536,16 +536,15 @@ class SSH1 /** * Connect to an SSHv1 server * - * @return bool - * @throws \UnexpectedValueException on receipt of unexpected packets - * @throws \RuntimeException on other errors + * @return Boolean * @access private */ function _connect() { $this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->connectionTimeout); if (!$this->fsock) { - throw new \RuntimeException(rtrim("Cannot connect to $host. Error $errno. $errstr")); + user_error(rtrim("Cannot connect to {$this->host}:{$this->port}. Error $errno. $errstr")); + return false; } $this->server_identification = $init_line = fgets($this->fsock, 255); @@ -556,17 +555,20 @@ class SSH1 } if (!preg_match('#SSH-([0-9\.]+)-(.+)#', $init_line, $parts)) { - throw new \RuntimeException('Can only connect to SSH servers'); + user_error('Can only connect to SSH servers'); + return false; } if ($parts[1][0] != 1) { - throw new \RuntimeException("Cannot connect to $parts[1] servers"); + user_error("Cannot connect to SSH $parts[1] servers"); + return false; } fputs($this->fsock, $this->identifier."\r\n"); $response = $this->_get_binary_packet(); if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_PUBLIC_KEY) { - throw new \UnexpectedValueException('Expected SSH_SMSG_PUBLIC_KEY'); + user_error('Expected SSH_SMSG_PUBLIC_KEY'); + return false; } $anti_spoofing_cookie = $this->_string_shift($response[self::RESPONSE_DATA], 8); @@ -650,7 +652,8 @@ 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)) { - throw new \RuntimeException('Error sending SSH_CMSG_SESSION_KEY'); + user_error('Error sending SSH_CMSG_SESSION_KEY'); + return false; } switch ($cipher) { @@ -658,20 +661,16 @@ class SSH1 // $this->crypto = new \phpseclib\Crypt\Null(); // break; case self::CIPHER_DES: - $this->crypto = new DES(DES::MODE_CBC); + $this->crypto = new DES(); $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(); @@ -683,7 +682,8 @@ class SSH1 $response = $this->_get_binary_packet(); if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) { - throw new \UnexpectedValueException('Expected SSH_SMSG_SUCCESS'); + user_error('Expected SSH_SMSG_SUCCESS'); + return false; } $this->bitmap = self::MASK_CONNECTED; @@ -694,11 +694,9 @@ class SSH1 /** * Login * - * @param string $username - * @param string $password - * @return bool - * @throws \UnexpectedValueException on receipt of unexpected packets - * @throws \RuntimeException on other errors + * @param String $username + * @param optional String $password + * @return Boolean * @access public */ function login($username, $password = '') @@ -717,7 +715,8 @@ class SSH1 $data = pack('CNa*', NET_SSH1_CMSG_USER, strlen($username), $username); if (!$this->_send_binary_packet($data)) { - throw new \RuntimeException('Error sending SSH_CMSG_USER'); + user_error('Error sending SSH_CMSG_USER'); + return false; } $response = $this->_get_binary_packet(); @@ -729,13 +728,15 @@ class SSH1 $this->bitmap |= self::MASK_LOGIN; return true; } elseif ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_FAILURE) { - throw new \UnexpectedValueException('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE'); + user_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE'); + return false; } $data = pack('CNa*', NET_SSH1_CMSG_AUTH_PASSWORD, strlen($password), $password); if (!$this->_send_binary_packet($data)) { - throw new \RuntimeException('Error sending SSH_CMSG_AUTH_PASSWORD'); + user_error('Error sending SSH_CMSG_AUTH_PASSWORD'); + return false; } // remove the username and password from the last logged packet @@ -755,7 +756,8 @@ class SSH1 } elseif ($response[self::RESPONSE_TYPE] == NET_SSH1_SMSG_FAILURE) { return false; } else { - throw new \UnexpectedValueException('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE'); + user_error('Expected SSH_SMSG_SUCCESS or SSH_SMSG_FAILURE'); + return false; } } @@ -765,7 +767,7 @@ class SSH1 * $ssh->exec('ping 127.0.0.1'); on a Linux host will never return and will run indefinitely. setTimeout() makes it so it'll timeout. * Setting $timeout to false or 0 will mean there is no timeout. * - * @param mixed $timeout + * @param Mixed $timeout */ function setTimeout($timeout) { @@ -786,23 +788,24 @@ class SSH1 * * Returns false on failure and the output, otherwise. * - * @see self::interactiveRead() - * @see self::interactiveWrite() - * @param string $cmd + * @see \phpseclib\Net\SSH1::interactiveRead() + * @see \phpseclib\Net\SSH1::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)) { - throw new \RuntimeException('Operation disallowed prior to login()'); + user_error('Operation disallowed prior to login()'); + return false; } $data = pack('CNa*', NET_SSH1_CMSG_EXEC_CMD, strlen($cmd), $cmd); if (!$this->_send_binary_packet($data)) { - throw new \RuntimeException('Error sending SSH_CMSG_EXEC_CMD'); + user_error('Error sending SSH_CMSG_EXEC_CMD'); + return false; } if (!$block) { @@ -835,11 +838,9 @@ class SSH1 /** * Creates an interactive shell * - * @see self::interactiveRead() - * @see self::interactiveWrite() - * @return bool - * @throws \UnexpectedValueException on receipt of unexpected packets - * @throws \RuntimeException on other errors + * @see \phpseclib\Net\SSH1::interactiveRead() + * @see \phpseclib\Net\SSH1::interactiveWrite() + * @return Boolean * @access private */ function _initShell() @@ -850,7 +851,8 @@ 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)) { - throw new \RuntimeException('Error sending SSH_CMSG_REQUEST_PTY'); + user_error('Error sending SSH_CMSG_REQUEST_PTY'); + return false; } $response = $this->_get_binary_packet(); @@ -859,13 +861,15 @@ class SSH1 return false; } if ($response[self::RESPONSE_TYPE] != NET_SSH1_SMSG_SUCCESS) { - throw new \UnexpectedValueException('Expected SSH_SMSG_SUCCESS'); + user_error('Expected SSH_SMSG_SUCCESS'); + return false; } $data = pack('C', NET_SSH1_CMSG_EXEC_SHELL); if (!$this->_send_binary_packet($data)) { - throw new \RuntimeException('Error sending SSH_CMSG_EXEC_SHELL'); + user_error('Error sending SSH_CMSG_EXEC_SHELL'); + return false; } $this->bitmap |= self::MASK_SHELL; @@ -878,9 +882,9 @@ class SSH1 /** * Inputs a command into an interactive shell. * - * @see self::interactiveWrite() - * @param string $cmd - * @return bool + * @see \phpseclib\Net\SSH1::interactiveWrite() + * @param String $cmd + * @return Boolean * @access public */ function write($cmd) @@ -894,21 +898,22 @@ class SSH1 * $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 + * @see \phpseclib\Net\SSH1::write() + * @param String $expect + * @param Integer $mode + * @return Boolean * @access public */ function read($expect, $mode = self::READ__SIMPLE) { if (!($this->bitmap & self::MASK_LOGIN)) { - throw new \RuntimeException('Operation disallowed prior to login()'); + user_error('Operation disallowed prior to login()'); + return false; } if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) { - throw new \RuntimeException('Unable to initiate an interactive shell session'); + user_error('Unable to initiate an interactive shell session'); + return false; } $match = $expect; @@ -933,26 +938,28 @@ class SSH1 /** * Inputs a command into an interactive shell. * - * @see self::interactiveRead() - * @param string $cmd - * @return bool - * @throws \RuntimeException on connection error + * @see \phpseclib\Net\SSH1::interactiveRead() + * @param String $cmd + * @return Boolean * @access public */ function interactiveWrite($cmd) { if (!($this->bitmap & self::MASK_LOGIN)) { - throw new \RuntimeException('Operation disallowed prior to login()'); + user_error('Operation disallowed prior to login()'); + return false; } if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) { - throw new \RuntimeException('Unable to initiate an interactive shell session'); + user_error('Unable to initiate an interactive shell session'); + return false; } $data = pack('CNa*', NET_SSH1_CMSG_STDIN_DATA, strlen($cmd), $cmd); if (!$this->_send_binary_packet($data)) { - throw new \RuntimeException('Error sending SSH_CMSG_STDIN'); + user_error('Error sending SSH_CMSG_STDIN'); + return false; } return true; @@ -967,19 +974,20 @@ class SSH1 * does not support ANSI escape sequences in Win32 Console applications", so if you're a Windows user, * there's not going to be much recourse. * - * @see self::interactiveRead() - * @return string - * @throws \RuntimeException on connection error + * @see \phpseclib\Net\SSH1::interactiveRead() + * @return String * @access public */ function interactiveRead() { if (!($this->bitmap & self::MASK_LOGIN)) { - throw new \RuntimeException('Operation disallowed prior to login()'); + user_error('Operation disallowed prior to login()'); + return false; } if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) { - throw new \RuntimeException('Unable to initiate an interactive shell session'); + user_error('Unable to initiate an interactive shell session'); + return false; } $read = array($this->fsock); @@ -1018,7 +1026,7 @@ class SSH1 /** * Disconnect * - * @param string $msg + * @param String $msg * @access private */ function _disconnect($msg = 'Client Quit') @@ -1055,8 +1063,8 @@ class SSH1 * Also, this function could be improved upon by adding detection for the following exploit: * http://www.securiteam.com/securitynews/5LP042K3FY.html * - * @see self::_send_binary_packet() - * @return array + * @see \phpseclib\Net\SSH1::_send_binary_packet() + * @return Array * @access private */ function _get_binary_packet() @@ -1131,9 +1139,9 @@ class SSH1 * * Returns true on success, false on failure. * - * @see self::_get_binary_packet() - * @param string $data - * @return bool + * @see \phpseclib\Net\SSH1::_get_binary_packet() + * @param String $data + * @return Boolean * @access private */ function _send_binary_packet($data) @@ -1178,10 +1186,10 @@ class SSH1 * we've reimplemented it. A more detailed discussion of the differences can be found after * $crc_lookup_table's initialization. * - * @see self::_get_binary_packet() - * @see self::_send_binary_packet() - * @param string $data - * @return int + * @see \phpseclib\Net\SSH1::_get_binary_packet() + * @see \phpseclib\Net\SSH1::_send_binary_packet() + * @param String $data + * @return Integer * @access private */ function _crc($data) @@ -1276,9 +1284,9 @@ class SSH1 * * Inspired by array_shift * - * @param string $string - * @param int $index - * @return string + * @param String $string + * @param optional Integer $index + * @return String * @access private */ function _string_shift(&$string, $index = 1) @@ -1295,9 +1303,9 @@ class SSH1 * should be a number with the property that gcd($e, ($p - 1) * ($q - 1)) == 1. Could just make anything that * calls this call modexp, instead, but I think this makes things clearer, maybe... * - * @see self::__construct() + * @see \phpseclib\Net\SSH1::__construct() * @param BigInteger $m - * @param array $key + * @param Array $key * @return BigInteger * @access private */ @@ -1305,9 +1313,9 @@ class SSH1 { /* $rsa = new RSA(); - $rsa->load($key, 'raw'); - $rsa->setHash('sha1'); - return $rsa->encrypt($m, RSA::PADDING_PKCS1); + $rsa->loadKey($key, RSA::PUBLIC_FORMAT_RAW); + $rsa->setEncryptionMode(RSA::ENCRYPTION_PKCS1); + return $rsa->encrypt($m); */ // To quote from protocol-1.5.txt: @@ -1346,7 +1354,7 @@ class SSH1 * named constants from it, using the value as the name of the constant and the index as the value of the constant. * If any of the constants that would be defined already exists, none of the constants will be defined. * - * @param array $array + * @param Array $array * @access private */ function _define_array() @@ -1369,7 +1377,7 @@ class SSH1 * Returns a string if NET_SSH1_LOGGING == self::LOG_COMPLEX, an array if NET_SSH1_LOGGING == self::LOG_SIMPLE and false if !defined('NET_SSH1_LOGGING') * * @access public - * @return array|false|string + * @return String or Array */ function getLog() { @@ -1392,10 +1400,10 @@ class SSH1 /** * Formats a log for printing * - * @param array $message_log - * @param array $message_number_log + * @param Array $message_log + * @param Array $message_number_log * @access private - * @return string + * @return String */ function _format_log($message_log, $message_number_log) { @@ -1428,9 +1436,9 @@ class SSH1 * * For use with preg_replace_callback() * - * @param array $matches + * @param Array $matches * @access private - * @return string + * @return String */ function _format_log_helper($matches) { @@ -1443,8 +1451,8 @@ class SSH1 * Returns, by default, the base-10 representation. If $raw_output is set to true, returns, instead, * the raw bytes. This behavior is similar to PHP's md5() function. * - * @param bool $raw_output - * @return string + * @param optional Boolean $raw_output + * @return String * @access public */ function getServerKeyPublicExponent($raw_output = false) @@ -1458,8 +1466,8 @@ class SSH1 * Returns, by default, the base-10 representation. If $raw_output is set to true, returns, instead, * the raw bytes. This behavior is similar to PHP's md5() function. * - * @param bool $raw_output - * @return string + * @param optional Boolean $raw_output + * @return String * @access public */ function getServerKeyPublicModulus($raw_output = false) @@ -1473,8 +1481,8 @@ class SSH1 * Returns, by default, the base-10 representation. If $raw_output is set to true, returns, instead, * the raw bytes. This behavior is similar to PHP's md5() function. * - * @param bool $raw_output - * @return string + * @param optional Boolean $raw_output + * @return String * @access public */ function getHostKeyPublicExponent($raw_output = false) @@ -1488,8 +1496,8 @@ class SSH1 * Returns, by default, the base-10 representation. If $raw_output is set to true, returns, instead, * the raw bytes. This behavior is similar to PHP's md5() function. * - * @param bool $raw_output - * @return string + * @param optional Boolean $raw_output + * @return String * @access public */ function getHostKeyPublicModulus($raw_output = false) @@ -1504,8 +1512,8 @@ class SSH1 * is set to true, returns, instead, an array of constants. ie. instead of array('Triple-DES in CBC mode'), you'll * get array(self::CIPHER_3DES). * - * @param bool $raw_output - * @return array + * @param optional Boolean $raw_output + * @return Array * @access public */ function getSupportedCiphers($raw_output = false) @@ -1520,8 +1528,8 @@ class SSH1 * is set to true, returns, instead, an array of constants. ie. instead of array('password authentication'), you'll * get array(self::AUTH_PASSWORD). * - * @param bool $raw_output - * @return array + * @param optional Boolean $raw_output + * @return Array * @access public */ function getSupportedAuthentications($raw_output = false) @@ -1532,7 +1540,7 @@ class SSH1 /** * Return the server identification. * - * @return string + * @return String * @access public */ function getServerIdentification() @@ -1545,7 +1553,7 @@ class SSH1 * * Makes sure that only the last 1MB worth of packets will be logged * - * @param string $data + * @param String $data * @access private */ function _append_log($protocol_flags, $message) diff --git a/phpseclib/Net/SSH2.php b/phpseclib/Net/SSH2.php index 7111b860..c25fb1ee 100644 --- a/phpseclib/Net/SSH2.php +++ b/phpseclib/Net/SSH2.php @@ -26,7 +26,7 @@ * * $key = new \phpseclib\Crypt\RSA(); * //$key->setPassword('whatever'); - * $key->load(file_get_contents('privatekey')); + * $key->loadKey(file_get_contents('privatekey')); * * $ssh = new \phpseclib\Net\SSH2('www.domain.tld'); * if (!$ssh->login('username', $key)) { @@ -60,7 +60,6 @@ use phpseclib\Crypt\TripleDES; use phpseclib\Crypt\Twofish; use phpseclib\Math\BigInteger; // Used to do Diffie-Hellman key exchange and DSA/RSA signature verification. use phpseclib\System\SSH\Agent; -use phpseclib\Exception\NoSupportedAlgorithmsException; /** * Pure-PHP implementation of SSHv2. @@ -113,19 +112,19 @@ class SSH2 */ /** * Returns the message numbers - */ + */ const LOG_SIMPLE = 1; /** * Returns the message content - */ + */ const LOG_COMPLEX = 2; /** * Outputs the content real-time - */ + */ const LOG_REALTIME = 3; /** * Dumps the content real-time to a file - */ + */ const LOG_REALTIME_FILE = 4; /**#@-*/ @@ -135,22 +134,22 @@ class SSH2 */ /** * Returns when a string matching $expect exactly is found - */ + */ const READ_SIMPLE = 1; /** * Returns when a string matching the regular expression $expect is found - */ + */ const READ_REGEX = 2; /** * Make sure that the log never gets larger than this - */ + */ const LOG_MAX_SIZE = 1048576; // 1024 * 1024 /**#@-*/ /** * The SSH identifier * - * @var string + * @var String * @access private */ var $identifier; @@ -158,7 +157,7 @@ class SSH2 /** * The Socket Object * - * @var object + * @var Object * @access private */ var $fsock; @@ -169,7 +168,7 @@ class SSH2 * The bits that are set represent functions that have been called already. This is used to determine * if a requisite function has been successfully executed. If not, an error should be thrown. * - * @var int + * @var Integer * @access private */ var $bitmap = 0; @@ -177,9 +176,9 @@ class SSH2 /** * Error information * - * @see self::getErrors() - * @see self::getLastError() - * @var string + * @see \phpseclib\Net\SSH2::getErrors() + * @see \phpseclib\Net\SSH2::getLastError() + * @var String * @access private */ var $errors = array(); @@ -187,8 +186,8 @@ class SSH2 /** * Server Identifier * - * @see self::getServerIdentification() - * @var array|false + * @see \phpseclib\Net\SSH2::getServerIdentification() + * @var mixed false or Array * @access private */ var $server_identifier = false; @@ -196,8 +195,8 @@ class SSH2 /** * Key Exchange Algorithms * - * @see self::getKexAlgorithims() - * @var array|false + * @see \phpseclib\Net\SSH2::getKexAlgorithims() + * @var mixed false or Array * @access private */ var $kex_algorithms = false; @@ -205,8 +204,8 @@ class SSH2 /** * Minimum Diffie-Hellman Group Bit Size in RFC 4419 Key Exchange Methods * - * @see self::_key_exchange() - * @var int + * @see Net_SSH2::_key_exchange() + * @var Integer * @access private */ var $kex_dh_group_size_min = 1536; @@ -214,8 +213,8 @@ class SSH2 /** * Preferred Diffie-Hellman Group Bit Size in RFC 4419 Key Exchange Methods * - * @see self::_key_exchange() - * @var int + * @see Net_SSH2::_key_exchange() + * @var Integer * @access private */ var $kex_dh_group_size_preferred = 2048; @@ -223,8 +222,8 @@ class SSH2 /** * Maximum Diffie-Hellman Group Bit Size in RFC 4419 Key Exchange Methods * - * @see self::_key_exchange() - * @var int + * @see Net_SSH2::_key_exchange() + * @var Integer * @access private */ var $kex_dh_group_size_max = 4096; @@ -232,8 +231,8 @@ class SSH2 /** * Server Host Key Algorithms * - * @see self::getServerHostKeyAlgorithms() - * @var array|false + * @see \phpseclib\Net\SSH2::getServerHostKeyAlgorithms() + * @var mixed false or Array * @access private */ var $server_host_key_algorithms = false; @@ -241,8 +240,8 @@ class SSH2 /** * Encryption Algorithms: Client to Server * - * @see self::getEncryptionAlgorithmsClient2Server() - * @var array|false + * @see \phpseclib\Net\SSH2::getEncryptionAlgorithmsClient2Server() + * @var mixed false or Array * @access private */ var $encryption_algorithms_client_to_server = false; @@ -250,8 +249,8 @@ class SSH2 /** * Encryption Algorithms: Server to Client * - * @see self::getEncryptionAlgorithmsServer2Client() - * @var array|false + * @see \phpseclib\Net\SSH2::getEncryptionAlgorithmsServer2Client() + * @var mixed false or Array * @access private */ var $encryption_algorithms_server_to_client = false; @@ -259,8 +258,8 @@ class SSH2 /** * MAC Algorithms: Client to Server * - * @see self::getMACAlgorithmsClient2Server() - * @var array|false + * @see \phpseclib\Net\SSH2::getMACAlgorithmsClient2Server() + * @var mixed false or Array * @access private */ var $mac_algorithms_client_to_server = false; @@ -268,8 +267,8 @@ class SSH2 /** * MAC Algorithms: Server to Client * - * @see self::getMACAlgorithmsServer2Client() - * @var array|false + * @see \phpseclib\Net\SSH2::getMACAlgorithmsServer2Client() + * @var mixed false or Array * @access private */ var $mac_algorithms_server_to_client = false; @@ -277,8 +276,8 @@ class SSH2 /** * Compression Algorithms: Client to Server * - * @see self::getCompressionAlgorithmsClient2Server() - * @var array|false + * @see \phpseclib\Net\SSH2::getCompressionAlgorithmsClient2Server() + * @var mixed false or Array * @access private */ var $compression_algorithms_client_to_server = false; @@ -286,8 +285,8 @@ class SSH2 /** * Compression Algorithms: Server to Client * - * @see self::getCompressionAlgorithmsServer2Client() - * @var array|false + * @see \phpseclib\Net\SSH2::getCompressionAlgorithmsServer2Client() + * @var mixed false or Array * @access private */ var $compression_algorithms_server_to_client = false; @@ -295,8 +294,8 @@ class SSH2 /** * Languages: Server to Client * - * @see self::getLanguagesServer2Client() - * @var array|false + * @see \phpseclib\Net\SSH2::getLanguagesServer2Client() + * @var mixed false or Array * @access private */ var $languages_server_to_client = false; @@ -304,8 +303,8 @@ class SSH2 /** * Languages: Client to Server * - * @see self::getLanguagesClient2Server() - * @var array|false + * @see \phpseclib\Net\SSH2::getLanguagesClient2Server() + * @var mixed false or Array * @access private */ var $languages_client_to_server = false; @@ -320,9 +319,9 @@ class SSH2 * * -- http://tools.ietf.org/html/rfc4253#section-6 * - * @see self::__construct() - * @see self::_send_binary_packet() - * @var int + * @see \phpseclib\Net\SSH2::__construct() + * @see \phpseclib\Net\SSH2::_send_binary_packet() + * @var Integer * @access private */ var $encrypt_block_size = 8; @@ -330,9 +329,9 @@ class SSH2 /** * Block Size for Client to Server Encryption * - * @see self::__construct() - * @see self::_get_binary_packet() - * @var int + * @see \phpseclib\Net\SSH2::__construct() + * @see \phpseclib\Net\SSH2::_get_binary_packet() + * @var Integer * @access private */ var $decrypt_block_size = 8; @@ -340,8 +339,8 @@ class SSH2 /** * Server to Client Encryption Object * - * @see self::_get_binary_packet() - * @var object + * @see \phpseclib\Net\SSH2::_get_binary_packet() + * @var Object * @access private */ var $decrypt = false; @@ -349,8 +348,8 @@ class SSH2 /** * Client to Server Encryption Object * - * @see self::_send_binary_packet() - * @var object + * @see \phpseclib\Net\SSH2::_send_binary_packet() + * @var Object * @access private */ var $encrypt = false; @@ -358,8 +357,8 @@ class SSH2 /** * Client to Server HMAC Object * - * @see self::_send_binary_packet() - * @var object + * @see \phpseclib\Net\SSH2::_send_binary_packet() + * @var Object * @access private */ var $hmac_create = false; @@ -367,8 +366,8 @@ class SSH2 /** * Server to Client HMAC Object * - * @see self::_get_binary_packet() - * @var object + * @see \phpseclib\Net\SSH2::_get_binary_packet() + * @var Object * @access private */ var $hmac_check = false; @@ -380,8 +379,8 @@ class SSH2 * For the client to server side, the HMAC object will make the HMAC as long as it needs to be. All we need to do is * append it. * - * @see self::_get_binary_packet() - * @var int + * @see \phpseclib\Net\SSH2::_get_binary_packet() + * @var Integer * @access private */ var $hmac_size = false; @@ -389,8 +388,8 @@ class SSH2 /** * Server Public Host Key * - * @see self::getServerPublicHostKey() - * @var string + * @see \phpseclib\Net\SSH2::getServerPublicHostKey() + * @var String * @access private */ var $server_public_host_key; @@ -404,8 +403,8 @@ class SSH2 * * -- http://tools.ietf.org/html/rfc4253#section-7.2 * - * @see self::_key_exchange() - * @var string + * @see \phpseclib\Net\SSH2::_key_exchange() + * @var String * @access private */ var $session_id = false; @@ -415,8 +414,8 @@ class SSH2 * * The current exchange hash * - * @see self::_key_exchange() - * @var string + * @see \phpseclib\Net\SSH2::_key_exchange() + * @var String * @access private */ var $exchange_hash = false; @@ -424,8 +423,8 @@ class SSH2 /** * Message Numbers * - * @see self::__construct() - * @var array + * @see \phpseclib\Net\SSH2::__construct() + * @var Array * @access private */ var $message_numbers = array(); @@ -433,8 +432,8 @@ class SSH2 /** * Disconnection Message 'reason codes' defined in RFC4253 * - * @see self::__construct() - * @var array + * @see \phpseclib\Net\SSH2::__construct() + * @var Array * @access private */ var $disconnect_reasons = array(); @@ -442,8 +441,8 @@ class SSH2 /** * SSH_MSG_CHANNEL_OPEN_FAILURE 'reason codes', defined in RFC4254 * - * @see self::__construct() - * @var array + * @see \phpseclib\Net\SSH2::__construct() + * @var Array * @access private */ var $channel_open_failure_reasons = array(); @@ -452,8 +451,8 @@ class SSH2 * Terminal Modes * * @link http://tools.ietf.org/html/rfc4254#section-8 - * @see self::__construct() - * @var array + * @see \phpseclib\Net\SSH2::__construct() + * @var Array * @access private */ var $terminal_modes = array(); @@ -462,8 +461,8 @@ class SSH2 * SSH_MSG_CHANNEL_EXTENDED_DATA's data_type_codes * * @link http://tools.ietf.org/html/rfc4254#section-5.2 - * @see self::__construct() - * @var array + * @see \phpseclib\Net\SSH2::__construct() + * @var Array * @access private */ var $channel_extended_data_type_codes = array(); @@ -473,8 +472,8 @@ class SSH2 * * See 'Section 6.4. Data Integrity' of rfc4253 for more info. * - * @see self::_send_binary_packet() - * @var int + * @see \phpseclib\Net\SSH2::_send_binary_packet() + * @var Integer * @access private */ var $send_seq_no = 0; @@ -484,8 +483,8 @@ class SSH2 * * See 'Section 6.4. Data Integrity' of rfc4253 for more info. * - * @see self::_get_binary_packet() - * @var int + * @see \phpseclib\Net\SSH2::_get_binary_packet() + * @var Integer * @access private */ var $get_seq_no = 0; @@ -495,9 +494,9 @@ class SSH2 * * Maps client channels to server channels * - * @see self::_get_channel_packet() - * @see self::exec() - * @var array + * @see \phpseclib\Net\SSH2::_get_channel_packet() + * @see \phpseclib\Net\SSH2::exec() + * @var Array * @access private */ var $server_channels = array(); @@ -508,9 +507,9 @@ class SSH2 * If a client requests a packet from one channel but receives two packets from another those packets should * be placed in a buffer * - * @see self::_get_channel_packet() - * @see self::exec() - * @var array + * @see \phpseclib\Net\SSH2::_get_channel_packet() + * @see \phpseclib\Net\SSH2::exec() + * @var Array * @access private */ var $channel_buffers = array(); @@ -520,8 +519,8 @@ class SSH2 * * Contains the type of the last sent message * - * @see self::_get_channel_packet() - * @var array + * @see \phpseclib\Net\SSH2::_get_channel_packet() + * @var Array * @access private */ var $channel_status = array(); @@ -531,8 +530,8 @@ class SSH2 * * Maximum packet size indexed by channel * - * @see self::_send_channel_packet() - * @var array + * @see \phpseclib\Net\SSH2::_send_channel_packet() + * @var Array * @access private */ var $packet_size_client_to_server = array(); @@ -540,8 +539,8 @@ class SSH2 /** * Message Number Log * - * @see self::getLog() - * @var array + * @see \phpseclib\Net\SSH2::getLog() + * @var Array * @access private */ var $message_number_log = array(); @@ -549,8 +548,8 @@ class SSH2 /** * Message Log * - * @see self::getLog() - * @var array + * @see \phpseclib\Net\SSH2::getLog() + * @var Array * @access private */ var $message_log = array(); @@ -560,9 +559,9 @@ class SSH2 * * Bytes the other party can send before it must wait for the window to be adjusted (0x7FFFFFFF = 2GB) * - * @var int - * @see self::_send_channel_packet() - * @see self::exec() + * @var Integer + * @see \phpseclib\Net\SSH2::_send_channel_packet() + * @see \phpseclib\Net\SSH2::exec() * @access private */ var $window_size = 0x7FFFFFFF; @@ -572,8 +571,8 @@ class SSH2 * * Window size indexed by channel * - * @see self::_send_channel_packet() - * @var array + * @see \phpseclib\Net\SSH2::_send_channel_packet() + * @var Array * @access private */ var $window_size_server_to_client = array(); @@ -583,8 +582,8 @@ class SSH2 * * Window size indexed by channel * - * @see self::_get_channel_packet() - * @var array + * @see \phpseclib\Net\SSH2::_get_channel_packet() + * @var Array * @access private */ var $window_size_client_to_server = array(); @@ -594,8 +593,8 @@ class SSH2 * * Verified against $this->session_id * - * @see self::getServerPublicHostKey() - * @var string + * @see \phpseclib\Net\SSH2::getServerPublicHostKey() + * @var String * @access private */ var $signature = ''; @@ -605,8 +604,8 @@ class SSH2 * * ssh-rsa or ssh-dss. * - * @see self::getServerPublicHostKey() - * @var string + * @see \phpseclib\Net\SSH2::getServerPublicHostKey() + * @var String * @access private */ var $signature_format = ''; @@ -614,8 +613,8 @@ class SSH2 /** * Interactive Buffer * - * @see self::read() - * @var array + * @see \phpseclib\Net\SSH2::read() + * @var Array * @access private */ var $interactiveBuffer = ''; @@ -625,9 +624,9 @@ class SSH2 * * Should never exceed self::LOG_MAX_SIZE * - * @see self::_send_binary_packet() - * @see self::_get_binary_packet() - * @var int + * @see \phpseclib\Net\SSH2::_send_binary_packet() + * @see \phpseclib\Net\SSH2::_get_binary_packet() + * @var Integer * @access private */ var $log_size; @@ -635,7 +634,7 @@ class SSH2 /** * Timeout * - * @see self::setTimeout() + * @see \phpseclib\Net\SSH2::setTimeout() * @access private */ var $timeout; @@ -643,7 +642,7 @@ class SSH2 /** * Current Timeout * - * @see self::_get_channel_packet() + * @see \phpseclib\Net\SSH2::_get_channel_packet() * @access private */ var $curTimeout; @@ -651,8 +650,8 @@ class SSH2 /** * Real-time log file pointer * - * @see self::_append_log() - * @var resource + * @see \phpseclib\Net\SSH2::_append_log() + * @var Resource * @access private */ var $realtime_log_file; @@ -660,8 +659,8 @@ class SSH2 /** * Real-time log file size * - * @see self::_append_log() - * @var int + * @see \phpseclib\Net\SSH2::_append_log() + * @var Integer * @access private */ var $realtime_log_size; @@ -669,8 +668,8 @@ class SSH2 /** * Has the signature been validated? * - * @see self::getServerPublicHostKey() - * @var bool + * @see \phpseclib\Net\SSH2::getServerPublicHostKey() + * @var Boolean * @access private */ var $signature_validated = false; @@ -678,7 +677,7 @@ class SSH2 /** * Real-time log file wrap boolean * - * @see self::_append_log() + * @see \phpseclib\Net\SSH2::_append_log() * @access private */ var $realtime_log_wrap; @@ -686,7 +685,7 @@ class SSH2 /** * Flag to suppress stderr from output * - * @see self::enableQuietMode() + * @see \phpseclib\Net\SSH2::enableQuietMode() * @access private */ var $quiet_mode = false; @@ -694,7 +693,7 @@ class SSH2 /** * Time of first network activity * - * @var int + * @var Integer * @access private */ var $last_packet; @@ -702,7 +701,7 @@ class SSH2 /** * Exit status returned from ssh if any * - * @var int + * @var Integer * @access private */ var $exit_status; @@ -710,8 +709,8 @@ class SSH2 /** * Flag to request a PTY when using exec() * - * @var bool - * @see self::enablePTY() + * @var Boolean + * @see \phpseclib\Net\SSH2::enablePTY() * @access private */ var $request_pty = false; @@ -719,7 +718,7 @@ class SSH2 /** * Flag set while exec() is running when using enablePTY() * - * @var bool + * @var Boolean * @access private */ var $in_request_pty_exec = false; @@ -727,7 +726,7 @@ class SSH2 /** * Flag set after startSubsystem() is called * - * @var bool + * @var Boolean * @access private */ var $in_subsystem; @@ -735,7 +734,7 @@ class SSH2 /** * Contents of stdError * - * @var string + * @var String * @access private */ var $stdErrorLog; @@ -743,8 +742,8 @@ class SSH2 /** * The Last Interactive Response * - * @see self::_keyboard_interactive_process() - * @var string + * @see \phpseclib\Net\SSH2::_keyboard_interactive_process() + * @var String * @access private */ var $last_interactive_response = ''; @@ -752,8 +751,8 @@ class SSH2 /** * Keyboard Interactive Request / Responses * - * @see self::_keyboard_interactive_process() - * @var array + * @see \phpseclib\Net\SSH2::_keyboard_interactive_process() + * @var Array * @access private */ var $keyboard_requests_responses = array(); @@ -764,9 +763,9 @@ class SSH2 * Quoting from the RFC, "in some jurisdictions, sending a warning message before * authentication may be relevant for getting legal protection." * - * @see self::_filter() - * @see self::getBannerMessage() - * @var string + * @see \phpseclib\Net\SSH2::_filter() + * @see \phpseclib\Net\SSH2::getBannerMessage() + * @var String * @access private */ var $banner_message = ''; @@ -774,8 +773,8 @@ class SSH2 /** * Did read() timeout or return normally? * - * @see self::isTimeout() - * @var bool + * @see \phpseclib\Net\SSH2::isTimeout() + * @var Boolean * @access private */ var $is_timeout = false; @@ -783,8 +782,8 @@ class SSH2 /** * Log Boundary * - * @see self::_format_log() - * @var string + * @see \phpseclib\Net\SSH2::_format_log() + * @var String * @access private */ var $log_boundary = ':'; @@ -792,8 +791,8 @@ class SSH2 /** * Log Long Width * - * @see self::_format_log() - * @var int + * @see \phpseclib\Net\SSH2::_format_log() + * @var Integer * @access private */ var $log_long_width = 65; @@ -801,8 +800,8 @@ class SSH2 /** * Log Short Width * - * @see self::_format_log() - * @var int + * @see \phpseclib\Net\SSH2::_format_log() + * @var Integer * @access private */ var $log_short_width = 16; @@ -810,9 +809,9 @@ class SSH2 /** * Hostname * - * @see self::__construct() - * @see self::_connect() - * @var string + * @see \phpseclib\Net\SSH2::__construct() + * @see \phpseclib\Net\SSH2::_connect() + * @var String * @access private */ var $host; @@ -820,9 +819,9 @@ class SSH2 /** * Port Number * - * @see self::__construct() - * @see self::_connect() - * @var int + * @see \phpseclib\Net\SSH2::__construct() + * @see \phpseclib\Net\SSH2::_connect() + * @var Integer * @access private */ var $port; @@ -830,10 +829,10 @@ class SSH2 /** * Number of columns for terminal window size * - * @see self::getWindowColumns() - * @see self::setWindowColumns() - * @see self::setWindowSize() - * @var int + * @see \phpseclib\Net\SSH2::getWindowColumns() + * @see \phpseclib\Net\SSH2::setWindowColumns() + * @see \phpseclib\Net\SSH2::setWindowSize() + * @var Integer * @access private */ var $windowColumns = 80; @@ -841,10 +840,10 @@ class SSH2 /** * Number of columns for terminal window size * - * @see self::getWindowRows() - * @see self::setWindowRows() - * @see self::setWindowSize() - * @var int + * @see \phpseclib\Net\SSH2::getWindowRows() + * @see \phpseclib\Net\SSH2::setWindowRows() + * @see \phpseclib\Net\SSH2::setWindowSize() + * @var Integer * @access private */ var $windowRows = 24; @@ -852,9 +851,9 @@ class SSH2 /** * Crypto Engine * - * @see self::setCryptoEngine() - * @see self::_key_exchange() - * @var int + * @see Net_SSH2::setCryptoEngine() + * @see Net_SSH2::_key_exchange() + * @var Integer * @access private */ var $crypto_engine = false; @@ -867,23 +866,15 @@ class SSH2 */ var $agent; - /** - * Connection storage to replicates ssh2 extension functionality: - * {@link http://php.net/manual/en/wrappers.ssh2.php#refsect1-wrappers.ssh2-examples} - * - * @var SSH2[] - */ - static $connections; - /** * Default Constructor. * * $host can either be a string, representing the host, or a stream resource. * - * @param mixed $host - * @param int $port - * @param int $timeout - * @see self::login() + * @param Mixed $host + * @param optional Integer $port + * @param optional Integer $timeout + * @see \phpseclib\Net\SSH2::login() * @return \phpseclib\Net\SSH2 * @access public */ @@ -968,8 +959,6 @@ class SSH2 31 => 'NET_SSH2_MSG_KEX_ECDH_REPLY') ); - self::$connections[$this->getResourceId()] = $this; - if (is_resource($host)) { $this->fsock = $host; return; @@ -988,7 +977,7 @@ class SSH2 * Possible $engine values: * CRYPT_MODE_INTERNAL, CRYPT_MODE_MCRYPT * - * @param int $engine + * @param Integer $engine * @access private */ function setCryptoEngine($engine) @@ -999,9 +988,7 @@ class SSH2 /** * Connect to an SSHv2 server * - * @return bool - * @throws \UnexpectedValueException on receipt of unexpected packets - * @throws \RuntimeException on other errors + * @return Boolean * @access private */ function _connect() @@ -1021,7 +1008,8 @@ class SSH2 $this->fsock = @fsockopen($this->host, $this->port, $errno, $errstr, $this->curTimeout); if (!$this->fsock) { $host = $this->host . ':' . $this->port; - throw new \RuntimeException(rtrim("Cannot connect to $host. Error $errno. $errstr")); + user_error(rtrim("Cannot connect to $host. Error $errno. $errstr")); + return false; } $elapsed = microtime(true) - $start; @@ -1072,7 +1060,8 @@ class SSH2 } if (feof($this->fsock)) { - throw new \RuntimeException('Connection closed by server'); + user_error('Connection closed by server'); + return false; } $this->identifier = $this->_generate_identifier(); @@ -1088,18 +1077,21 @@ class SSH2 } if ($matches[1] != '1.99' && $matches[1] != '2.0') { - throw new \RuntimeException("Cannot connect to SSH $matches[1] servers"); + user_error("Cannot connect to SSH $matches[1] servers"); + return false; } fputs($this->fsock, $this->identifier . "\r\n"); $response = $this->_get_binary_packet(); if ($response === false) { - throw new \RuntimeException('Connection closed by server'); + user_error('Connection closed by server'); + return false; } if (ord($response[0]) != NET_SSH2_MSG_KEXINIT) { - throw new \UnexpectedValueException('Expected SSH_MSG_KEXINIT'); + user_error('Expected SSH_MSG_KEXINIT'); + return false; } if (!$this->_key_exchange($response)) { @@ -1117,7 +1109,7 @@ class SSH2 * You should overwrite this method in your own class if you want to use another identifier * * @access protected - * @return string + * @return String */ function _generate_identifier() { @@ -1150,15 +1142,12 @@ class SSH2 /** * Key Exchange * - * @param string $kexinit_payload_server - * @throws \UnexpectedValueException on receipt of unexpected packets - * @throws \RuntimeException on other errors - * @throws \phpseclib\Exception\NoSupportedAlgorithmsException when none of the algorithms phpseclib has loaded are compatible + * @param String $kexinit_payload_server * @access private */ function _key_exchange($kexinit_payload_server) { - $kex_algorithms = array( + static $kex_algorithms = array( // Elliptic Curve Diffie-Hellman Key Agreement (ECDH) using // Curve25519. See doc/curve25519-sha256@libssh.org.txt in the // libssh repository for more information. @@ -1171,94 +1160,97 @@ class SSH2 'diffie-hellman-group-exchange-sha1', // RFC 4419 'diffie-hellman-group-exchange-sha256', // RFC 4419 ); - if (!function_exists('\\Sodium\\library_version_major')) { + if (!class_exists('\Sodium')) { $kex_algorithms = array_diff( $kex_algorithms, array('curve25519-sha256@libssh.org') ); } - $server_host_key_algorithms = array( + static $server_host_key_algorithms = array( 'ssh-rsa', // RECOMMENDED sign Raw RSA Key 'ssh-dss' // REQUIRED sign Raw DSS Key ); - $encryption_algorithms = array( - // from : - 'arcfour256', - 'arcfour128', + static $encryption_algorithms = false; + if ($encryption_algorithms === false) { + $encryption_algorithms = array( + // from : + 'arcfour256', + 'arcfour128', - //'arcfour', // OPTIONAL the ARCFOUR stream cipher with a 128-bit key + //'arcfour', // OPTIONAL the ARCFOUR stream cipher with a 128-bit key - // CTR modes from : - 'aes128-ctr', // RECOMMENDED AES (Rijndael) in SDCTR mode, with 128-bit key - 'aes192-ctr', // RECOMMENDED AES with 192-bit key - 'aes256-ctr', // RECOMMENDED AES with 256-bit key + // CTR modes from : + 'aes128-ctr', // RECOMMENDED AES (Rijndael) in SDCTR mode, with 128-bit key + 'aes192-ctr', // RECOMMENDED AES with 192-bit key + 'aes256-ctr', // RECOMMENDED AES with 256-bit key - 'twofish128-ctr', // OPTIONAL Twofish in SDCTR mode, with 128-bit key - 'twofish192-ctr', // OPTIONAL Twofish with 192-bit key - 'twofish256-ctr', // OPTIONAL Twofish with 256-bit key + 'twofish128-ctr', // OPTIONAL Twofish in SDCTR mode, with 128-bit key + 'twofish192-ctr', // OPTIONAL Twofish with 192-bit key + 'twofish256-ctr', // OPTIONAL Twofish with 256-bit key - 'aes128-cbc', // RECOMMENDED AES with a 128-bit key - 'aes192-cbc', // OPTIONAL AES with a 192-bit key - 'aes256-cbc', // OPTIONAL AES in CBC mode, with a 256-bit key + 'aes128-cbc', // RECOMMENDED AES with a 128-bit key + 'aes192-cbc', // OPTIONAL AES with a 192-bit key + 'aes256-cbc', // OPTIONAL AES in CBC mode, with a 256-bit key - 'twofish128-cbc', // OPTIONAL Twofish with a 128-bit key - 'twofish192-cbc', // OPTIONAL Twofish with a 192-bit key - 'twofish256-cbc', - 'twofish-cbc', // OPTIONAL alias for "twofish256-cbc" - // (this is being retained for historical reasons) + 'twofish128-cbc', // OPTIONAL Twofish with a 128-bit key + 'twofish192-cbc', // OPTIONAL Twofish with a 192-bit key + 'twofish256-cbc', + 'twofish-cbc', // OPTIONAL alias for "twofish256-cbc" + // (this is being retained for historical reasons) - 'blowfish-ctr', // OPTIONAL Blowfish in SDCTR mode + 'blowfish-ctr', // OPTIONAL Blowfish in SDCTR mode - 'blowfish-cbc', // OPTIONAL Blowfish in CBC mode + 'blowfish-cbc', // OPTIONAL Blowfish in CBC mode - '3des-ctr', // RECOMMENDED Three-key 3DES in SDCTR mode + '3des-ctr', // RECOMMENDED Three-key 3DES in SDCTR mode - '3des-cbc', // REQUIRED three-key 3DES in CBC mode - //'none' // OPTIONAL no encryption; NOT RECOMMENDED - ); - - if (extension_loaded('openssl') && !extension_loaded('mcrypt')) { - // OpenSSL does not support arcfour256 in any capacity and arcfour128 / arcfour support is limited to - // instances that do not use continuous buffers - $encryption_algorithms = array_diff( - $encryption_algorithms, - array('arcfour256', 'arcfour128', 'arcfour') + '3des-cbc', // REQUIRED three-key 3DES in CBC mode + //'none' // OPTIONAL no encryption; NOT RECOMMENDED ); - } - if (class_exists('\phpseclib\Crypt\RC4') === false) { - $encryption_algorithms = array_diff( - $encryption_algorithms, - array('arcfour256', 'arcfour128', 'arcfour') - ); + if (extension_loaded('openssl') && !extension_loaded('mcrypt')) { + // OpenSSL does not support arcfour256 in any capacity and arcfour128 / arcfour support is limited to + // instances that do not use continuous buffers + $encryption_algorithms = array_diff( + $encryption_algorithms, + array('arcfour256', 'arcfour128', 'arcfour') + ); + } + + if (class_exists('\phpseclib\Crypt\RC4') === false) { + $encryption_algorithms = array_diff( + $encryption_algorithms, + array('arcfour256', 'arcfour128', 'arcfour') + ); + } + if (class_exists('\phpseclib\Crypt\Rijndael') === false) { + $encryption_algorithms = array_diff( + $encryption_algorithms, + array('aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'aes128-cbc', 'aes192-cbc', 'aes256-cbc') + ); + } + if (class_exists('\phpseclib\Crypt\Twofish') === false) { + $encryption_algorithms = array_diff( + $encryption_algorithms, + array('twofish128-ctr', 'twofish192-ctr', 'twofish256-ctr', 'twofish128-cbc', 'twofish192-cbc', 'twofish256-cbc', 'twofish-cbc') + ); + } + if (class_exists('\phpseclib\Crypt\Blowfish') === false) { + $encryption_algorithms = array_diff( + $encryption_algorithms, + array('blowfish-ctr', 'blowfish-cbc') + ); + } + if (class_exists('\phpseclib\Crypt\TripleDES') === false) { + $encryption_algorithms = array_diff( + $encryption_algorithms, + array('3des-ctr', '3des-cbc') + ); + } + $encryption_algorithms = array_values($encryption_algorithms); } - if (class_exists('\phpseclib\Crypt\Rijndael') === false) { - $encryption_algorithms = array_diff( - $encryption_algorithms, - array('aes128-ctr', 'aes192-ctr', 'aes256-ctr', 'aes128-cbc', 'aes192-cbc', 'aes256-cbc') - ); - } - if (class_exists('\phpseclib\Crypt\Twofish') === false) { - $encryption_algorithms = array_diff( - $encryption_algorithms, - array('twofish128-ctr', 'twofish192-ctr', 'twofish256-ctr', 'twofish128-cbc', 'twofish192-cbc', 'twofish256-cbc', 'twofish-cbc') - ); - } - if (class_exists('\phpseclib\Crypt\Blowfish') === false) { - $encryption_algorithms = array_diff( - $encryption_algorithms, - array('blowfish-ctr', 'blowfish-cbc') - ); - } - if (class_exists('\phpseclib\Crypt\TripleDES') === false) { - $encryption_algorithms = array_diff( - $encryption_algorithms, - array('3des-ctr', '3des-cbc') - ); - } - $encryption_algorithms = array_values($encryption_algorithms); $mac_algorithms = array( // from : @@ -1271,7 +1263,7 @@ class SSH2 //'none' // OPTIONAL no MAC; NOT RECOMMENDED ); - $compression_algorithms = array( + static $compression_algorithms = array( 'none' // REQUIRED no compression //'zlib' // OPTIONAL ZLIB (LZ77) compression ); @@ -1285,11 +1277,17 @@ class SSH2 )); } - $str_kex_algorithms = implode(',', $kex_algorithms); - $str_server_host_key_algorithms = implode(',', $server_host_key_algorithms); - $encryption_algorithms_server_to_client = $encryption_algorithms_client_to_server = implode(',', $encryption_algorithms); - $mac_algorithms_server_to_client = $mac_algorithms_client_to_server = implode(',', $mac_algorithms); - $compression_algorithms_server_to_client = $compression_algorithms_client_to_server = implode(',', $compression_algorithms); + static $str_kex_algorithms, $str_server_host_key_algorithms, + $encryption_algorithms_server_to_client, $mac_algorithms_server_to_client, $compression_algorithms_server_to_client, + $encryption_algorithms_client_to_server, $mac_algorithms_client_to_server, $compression_algorithms_client_to_server; + + if (empty($str_kex_algorithms)) { + $str_kex_algorithms = implode(',', $kex_algorithms); + $str_server_host_key_algorithms = implode(',', $server_host_key_algorithms); + $encryption_algorithms_server_to_client = $encryption_algorithms_client_to_server = implode(',', $encryption_algorithms); + $mac_algorithms_server_to_client = $mac_algorithms_client_to_server = implode(',', $mac_algorithms); + $compression_algorithms_server_to_client = $compression_algorithms_client_to_server = implode(',', $compression_algorithms); + } $client_cookie = Random::string(16); @@ -1365,28 +1363,27 @@ class SSH2 // here ends the second place. // we need to decide upon the symmetric encryption algorithms before we do the diffie-hellman key exchange - // we don't initialize any crypto-objects, yet - we do that, later. for now, we need the lengths to make the // diffie-hellman key exchange as fast as possible $decrypt = $this->_array_intersect_first($encryption_algorithms, $this->encryption_algorithms_server_to_client); $decryptKeyLength = $this->_encryption_algorithm_to_key_size($decrypt); if ($decryptKeyLength === null) { - $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new NoSupportedAlgorithmsException('No compatible server to client encryption algorithms found'); + user_error('No compatible server to client encryption algorithms found'); + return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); } $encrypt = $this->_array_intersect_first($encryption_algorithms, $this->encryption_algorithms_client_to_server); $encryptKeyLength = $this->_encryption_algorithm_to_key_size($encrypt); if ($encryptKeyLength === null) { - $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new NoSupportedAlgorithmsException('No compatible client to server encryption algorithms found'); + user_error('No compatible client to server encryption algorithms found'); + return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); } // through diffie-hellman key exchange a symmetric key is obtained $kex_algorithm = $this->_array_intersect_first($kex_algorithms, $this->kex_algorithms); if ($kex_algorithm === false) { - $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new NoSupportedAlgorithmsException('No compatible key exchange algorithms found'); + user_error('No compatible key exchange algorithms found'); + return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); } // Only relevant in diffie-hellman-group-exchange-sha{1,256}, otherwise empty. @@ -1394,7 +1391,7 @@ class SSH2 if ($kex_algorithm === 'curve25519-sha256@libssh.org') { $x = Random::string(32); - $eBytes = \Sodium\crypto_box_publickey_from_secretkey($x); + $eBytes = \Sodium::crypto_box_publickey_from_secretkey($x); $clientKexInitMessage = NET_SSH2_MSG_KEX_ECDH_INIT; $serverKexReplyMessage = NET_SSH2_MSG_KEX_ECDH_REPLY; $kexHash = new Hash('sha256'); @@ -1495,7 +1492,7 @@ class SSH2 $max = $one->bitwise_leftShift(16 * $keyLength); // 2 * 8 * $keyLength $max = $max->subtract($one); - $x = BigInteger::random($one, $max); + $x = $one->random($one, $max); $e = $g->modPow($x, $prime); $eBytes = $e->toBytes(true); @@ -1503,17 +1500,20 @@ class SSH2 $data = pack('CNa*', $clientKexInitMessage, strlen($eBytes), $eBytes); if (!$this->_send_binary_packet($data)) { - throw new \RuntimeException('Connection closed by server'); + user_error('Connection closed by server'); + return false; } $response = $this->_get_binary_packet(); if ($response === false) { - throw new \RuntimeException('Connection closed by server'); + user_error('Connection closed by server'); + return false; } extract(unpack('Ctype', $this->_string_shift($response, 1))); if ($type != $serverKexReplyMessage) { - throw new \UnexpectedValueException('Expected SSH_MSG_KEXDH_REPLY'); + user_error('Expected SSH_MSG_KEXDH_REPLY'); + return false; } $temp = unpack('Nlength', $this->_string_shift($response, 4)); @@ -1536,8 +1536,8 @@ class SSH2 user_error('Received curve25519 public key of invalid length.'); return false; } - $key = new BigInteger(\Sodium\crypto_scalarmult($x, $fBytes), 256); - \Sodium\memzero($x); + $key = new BigInteger(\Sodium::crypto_scalarmult($x, $fBytes), 256); + \Sodium::sodium_memzero($x); } else { $f = new BigInteger($fBytes, -256); $key = $f->modPow($x, $prime); @@ -1573,13 +1573,13 @@ class SSH2 $server_host_key_algorithm = $this->_array_intersect_first($server_host_key_algorithms, $this->server_host_key_algorithms); if ($server_host_key_algorithm === false) { - $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new NoSupportedAlgorithmsException('No compatible server host key algorithms found'); + user_error('No compatible server host key algorithms found'); + return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); } if ($public_key_format != $server_host_key_algorithm || $this->signature_format != $server_host_key_algorithm) { - $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new \RuntimeException('Server Host Key Algorithm Mismatch'); + user_error('Server Host Key Algorithm Mismatch'); + return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); } $packet = pack( @@ -1594,13 +1594,15 @@ class SSH2 $response = $this->_get_binary_packet(); if ($response === false) { - throw new \RuntimeException('Connection closed by server'); + user_error('Connection closed by server'); + return false; } extract(unpack('Ctype', $this->_string_shift($response, 1))); if ($type != NET_SSH2_MSG_NEWKEYS) { - throw new \UnexpectedValueException('Expected SSH_MSG_NEWKEYS'); + user_error('Expected SSH_MSG_NEWKEYS'); + return false; } $keyBytes = pack('Na*', strlen($keyBytes), $keyBytes); @@ -1616,13 +1618,11 @@ class SSH2 $this->encrypt->enableContinuousBuffer(); $this->encrypt->disablePadding(); - if ($this->encrypt->usesIV()) { - $iv = $kexHash->hash($keyBytes . $this->exchange_hash . 'A' . $this->session_id); - while ($this->encrypt_block_size > strlen($iv)) { - $iv.= $kexHash->hash($keyBytes . $this->exchange_hash . $iv); - } - $this->encrypt->setIV(substr($iv, 0, $this->encrypt_block_size)); + $iv = $kexHash->hash($keyBytes . $this->exchange_hash . 'A' . $this->session_id); + while ($this->encrypt_block_size > strlen($iv)) { + $iv.= $kexHash->hash($keyBytes . $this->exchange_hash . $iv); } + $this->encrypt->setIV(substr($iv, 0, $this->encrypt_block_size)); $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'C' . $this->session_id); while ($encryptKeyLength > strlen($key)) { @@ -1642,13 +1642,11 @@ class SSH2 $this->decrypt->enableContinuousBuffer(); $this->decrypt->disablePadding(); - if ($this->decrypt->usesIV()) { - $iv = $kexHash->hash($keyBytes . $this->exchange_hash . 'B' . $this->session_id); - while ($this->decrypt_block_size > strlen($iv)) { - $iv.= $kexHash->hash($keyBytes . $this->exchange_hash . $iv); - } - $this->decrypt->setIV(substr($iv, 0, $this->decrypt_block_size)); + $iv = $kexHash->hash($keyBytes . $this->exchange_hash . 'B' . $this->session_id); + while ($this->decrypt_block_size > strlen($iv)) { + $iv.= $kexHash->hash($keyBytes . $this->exchange_hash . $iv); } + $this->decrypt->setIV(substr($iv, 0, $this->decrypt_block_size)); $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'D' . $this->session_id); while ($decryptKeyLength > strlen($key)) { @@ -1673,8 +1671,8 @@ class SSH2 $mac_algorithm = $this->_array_intersect_first($mac_algorithms, $this->mac_algorithms_client_to_server); if ($mac_algorithm === false) { - $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new NoSupportedAlgorithmsException('No compatible client to server message authentication algorithms found'); + user_error('No compatible client to server message authentication algorithms found'); + return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); } $createKeyLength = 0; // ie. $mac_algorithm == 'none' @@ -1702,8 +1700,8 @@ class SSH2 $mac_algorithm = $this->_array_intersect_first($mac_algorithms, $this->mac_algorithms_server_to_client); if ($mac_algorithm === false) { - $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new NoSupportedAlgorithmsException('No compatible server to client message authentication algorithms found'); + user_error('No compatible server to client message authentication algorithms found'); + return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); } $checkKeyLength = 0; @@ -1749,15 +1747,15 @@ class SSH2 $compression_algorithm = $this->_array_intersect_first($compression_algorithms, $this->compression_algorithms_server_to_client); if ($compression_algorithm === false) { - $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new NoSupportedAlgorithmsException('No compatible server to client compression algorithms found'); + user_error('No compatible server to client compression algorithms found'); + return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); } $this->decompress = $compression_algorithm == 'zlib'; $compression_algorithm = $this->_array_intersect_first($compression_algorithms, $this->compression_algorithms_client_to_server); if ($compression_algorithm === false) { - $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new NoSupportedAlgorithmsException('No compatible client to server compression algorithms found'); + user_error('No compatible client to server compression algorithms found'); + return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); } $this->compress = $compression_algorithm == 'zlib'; @@ -1767,8 +1765,8 @@ class SSH2 /** * Maps an encryption algorithm name to the number of key bytes. * - * @param string $algorithm Name of the encryption algorithm - * @return int|null Number of bytes as an integer or null for unknown + * @param String $algorithm Name of the encryption algorithm + * @return Mixed Number of bytes as an integer or null for unknown * @access private */ function _encryption_algorithm_to_key_size($algorithm) @@ -1807,34 +1805,34 @@ class SSH2 * Maps an encryption algorithm name to an instance of a subclass of * \phpseclib\Crypt\Base. * - * @param string $algorithm Name of the encryption algorithm - * @return mixed Instance of \phpseclib\Crypt\Base or null for unknown + * @param String $algorithm Name of the encryption algorithm + * @return Mixed Instance of \phpseclib\Crypt\Base or null for unknown * @access private */ function _encryption_algorithm_to_crypt_instance($algorithm) { switch ($algorithm) { case '3des-cbc': - return new TripleDES(Base::MODE_CBC); + return new TripleDES(); case '3des-ctr': return new TripleDES(Base::MODE_CTR); case 'aes256-cbc': case 'aes192-cbc': case 'aes128-cbc': - return new Rijndael(Base::MODE_CBC); + return new Rijndael(); case 'aes256-ctr': case 'aes192-ctr': case 'aes128-ctr': return new Rijndael(Base::MODE_CTR); case 'blowfish-cbc': - return new Blowfish(Base::MODE_CBC); + return new Blowfish(); case 'blowfish-ctr': return new Blowfish(Base::MODE_CTR); case 'twofish128-cbc': case 'twofish192-cbc': case 'twofish256-cbc': case 'twofish-cbc': - return new Twofish(Base::MODE_CBC); + return new Twofish(); case 'twofish128-ctr': case 'twofish192-ctr': case 'twofish256-ctr': @@ -1852,11 +1850,11 @@ class SSH2 * * The $password parameter can be a plaintext password, a \phpseclib\Crypt\RSA object or an array * - * @param string $username - * @param mixed $password - * @param mixed $... - * @return bool - * @see self::_login() + * @param String $username + * @param Mixed $password + * @param Mixed $... + * @return Boolean + * @see _login * @access public */ function login($username) @@ -1868,11 +1866,11 @@ class SSH2 /** * Login Helper * - * @param string $username - * @param mixed $password - * @param mixed $... - * @return bool - * @see self::_login_helper() + * @param String $username + * @param Mixed $password + * @param Mixed $... + * @return Boolean + * @see _login_helper * @access private */ function _login($username) @@ -1899,11 +1897,9 @@ class SSH2 /** * Login Helper * - * @param string $username - * @param string $password - * @return bool - * @throws \UnexpectedValueException on receipt of unexpected packets - * @throws \RuntimeException on other errors + * @param String $username + * @param optional String $password + * @return Boolean * @access private * @internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis} * by sending dummy SSH_MSG_IGNORE messages. @@ -1928,13 +1924,15 @@ class SSH2 $response = $this->_get_binary_packet(); if ($response === false) { - throw new \RuntimeException('Connection closed by server'); + user_error('Connection closed by server'); + return false; } extract(unpack('Ctype', $this->_string_shift($response, 1))); if ($type != NET_SSH2_MSG_SERVICE_ACCEPT) { - throw new \UnexpectedValueException('Expected SSH_MSG_SERVICE_ACCEPT'); + user_error('Expected SSH_MSG_SERVICE_ACCEPT'); + return false; } $this->bitmap |= self::MASK_LOGIN_REQ; } @@ -1975,7 +1973,8 @@ class SSH2 $response = $this->_get_binary_packet(); if ($response === false) { - throw new \RuntimeException('Connection closed by server'); + user_error('Connection closed by server'); + return false; } extract(unpack('Ctype', $this->_string_shift($response, 1))); @@ -2029,7 +2028,8 @@ class SSH2 $response = $this->_get_binary_packet(); if ($response === false) { - throw new \RuntimeException('Connection closed by server'); + user_error('Connection closed by server'); + return false; } extract(unpack('Ctype', $this->_string_shift($response, 1))); @@ -2071,9 +2071,9 @@ class SSH2 * * See {@link http://tools.ietf.org/html/rfc4256 RFC4256} for details. This is not a full-featured keyboard-interactive authenticator. * - * @param string $username - * @param string $password - * @return bool + * @param String $username + * @param String $password + * @return Boolean * @access private */ function _keyboard_interactive_login($username, $password) @@ -2103,9 +2103,8 @@ class SSH2 /** * Handle the keyboard-interactive requests / responses. * - * @param string $responses... - * @return bool - * @throws \RuntimeException on connection error + * @param String $responses... + * @return Boolean * @access private */ function _keyboard_interactive_process() @@ -2117,7 +2116,8 @@ class SSH2 } else { $orig = $response = $this->_get_binary_packet(); if ($response === false) { - throw new \RuntimeException('Connection closed by server'); + user_error('Connection closed by server'); + return false; } } @@ -2217,9 +2217,9 @@ class SSH2 /** * Login with an ssh-agent provided key * - * @param string $username + * @param String $username * @param \phpseclib\System\SSH\Agent $agent - * @return bool + * @return Boolean * @access private */ function _ssh_agent_login($username, $agent) @@ -2238,10 +2238,9 @@ class SSH2 /** * Login with an RSA private key * - * @param string $username + * @param String $username * @param \phpseclib\Crypt\RSA $password - * @return bool - * @throws \RuntimeException on connection error + * @return Boolean * @access private * @internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis} * by sending dummy SSH_MSG_IGNORE messages. @@ -2249,7 +2248,7 @@ class SSH2 function _privatekey_login($username, $privatekey) { // see http://tools.ietf.org/html/rfc4253#page-15 - $publickey = $privatekey->getPublicKey('Raw'); + $publickey = $privatekey->getPublicKey(RSA::PUBLIC_FORMAT_RAW); if ($publickey === false) { return false; } @@ -2287,7 +2286,8 @@ class SSH2 $response = $this->_get_binary_packet(); if ($response === false) { - throw new \RuntimeException('Connection closed by server'); + user_error('Connection closed by server'); + return false; } extract(unpack('Ctype', $this->_string_shift($response, 1))); @@ -2310,8 +2310,8 @@ class SSH2 } $packet = $part1 . chr(1) . $part2; - $privatekey->setHash('sha1'); - $signature = $privatekey->sign(pack('Na*a*', strlen($this->session_id), $this->session_id, $packet), RSA::PADDING_PKCS1); + $privatekey->setSignatureMode(RSA::SIGNATURE_PKCS1); + $signature = $privatekey->sign(pack('Na*a*', strlen($this->session_id), $this->session_id, $packet)); $signature = pack('Na*Na*', strlen('ssh-rsa'), 'ssh-rsa', strlen($signature), $signature); $packet.= pack('Na*', strlen($signature), $signature); @@ -2321,7 +2321,8 @@ class SSH2 $response = $this->_get_binary_packet(); if ($response === false) { - throw new \RuntimeException('Connection closed by server'); + user_error('Connection closed by server'); + return false; } extract(unpack('Ctype', $this->_string_shift($response, 1))); @@ -2344,7 +2345,7 @@ class SSH2 * $ssh->exec('ping 127.0.0.1'); on a Linux host will never return and will run indefinitely. setTimeout() makes it so it'll timeout. * Setting $timeout to false or 0 will mean there is no timeout. * - * @param mixed $timeout + * @param Mixed $timeout * @access public */ function setTimeout($timeout) @@ -2368,10 +2369,9 @@ class SSH2 * If $callback is set to false then \phpseclib\Net\SSH2::_get_channel_packet(self::CHANNEL_EXEC) will need to be called manually. * In all likelihood, this is not a feature you want to be taking advantage of. * - * @param string $command - * @param Callback $callback - * @return string - * @throws \RuntimeException on connection error + * @param String $command + * @param optional Callback $callback + * @return String * @access public */ function exec($command, $callback = null) @@ -2439,7 +2439,8 @@ class SSH2 $response = $this->_get_binary_packet(); if ($response === false) { - throw new \RuntimeException('Connection closed by server'); + user_error('Connection closed by server'); + return false; } list(, $type) = unpack('C', $this->_string_shift($response, 1)); @@ -2449,8 +2450,8 @@ class SSH2 break; case NET_SSH2_MSG_CHANNEL_FAILURE: default: - $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); - throw new \RuntimeException('Unable to request pseudo-terminal'); + user_error('Unable to request pseudo-terminal'); + return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); } $this->in_request_pty_exec = true; } @@ -2515,11 +2516,9 @@ class SSH2 /** * Creates an interactive shell * - * @see self::read() - * @see self::write() - * @return bool - * @throws \UnexpectedValueException on receipt of unexpected packets - * @throws \RuntimeException on other errors + * @see \phpseclib\Net\SSH2::read() + * @see \phpseclib\Net\SSH2::write() + * @return Boolean * @access private */ function _initShell() @@ -2576,7 +2575,8 @@ class SSH2 $response = $this->_get_binary_packet(); if ($response === false) { - throw new \RuntimeException('Connection closed by server'); + user_error('Connection closed by server'); + return false; } list(, $type) = unpack('C', $this->_string_shift($response, 1)); @@ -2587,8 +2587,8 @@ class SSH2 case NET_SSH2_MSG_CHANNEL_FAILURE: break; default: - $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); - throw new \UnexpectedValueException('Unable to request pseudo-terminal'); + user_error('Unable to request pseudo-terminal'); + return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); } $packet = pack( @@ -2620,9 +2620,9 @@ class SSH2 /** * Return the channel to be used with read() / write() * - * @see self::read() - * @see self::write() - * @return int + * @see \phpseclib\Net\SSH2::read() + * @see \phpseclib\Net\SSH2::write() + * @return Integer * @access public */ function _get_interactive_channel() @@ -2640,7 +2640,7 @@ class SSH2 /** * Return an available open channel * - * @return int + * @return Integer * @access public */ function _get_open_channel() @@ -2661,11 +2661,10 @@ class SSH2 * Returns when there's a match for $expect, which 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 string - * @throws \RuntimeException on connection error + * @see \phpseclib\Net\SSH2::write() + * @param String $expect + * @param Integer $mode + * @return String * @access public */ function read($expect = '', $mode = self::READ_SIMPLE) @@ -2674,11 +2673,13 @@ class SSH2 $this->is_timeout = false; if (!($this->bitmap & self::MASK_LOGIN)) { - throw new \RuntimeException('Operation disallowed prior to login()'); + user_error('Operation disallowed prior to login()'); + return false; } if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) { - throw new \RuntimeException('Unable to initiate an interactive shell session'); + user_error('Unable to initiate an interactive shell session'); + return false; } $channel = $this->_get_interactive_channel(); @@ -2706,20 +2707,21 @@ class SSH2 /** * Inputs a command into an interactive shell. * - * @see self::read() - * @param string $cmd - * @return bool - * @throws \RuntimeException on connection error + * @see \phpseclib\Net\SSH2::read() + * @param String $cmd + * @return Boolean * @access public */ function write($cmd) { if (!($this->bitmap & self::MASK_LOGIN)) { - throw new \RuntimeException('Operation disallowed prior to login()'); + user_error('Operation disallowed prior to login()'); + return false; } if (!($this->bitmap & self::MASK_SHELL) && !$this->_initShell()) { - throw new \RuntimeException('Unable to initiate an interactive shell session'); + user_error('Unable to initiate an interactive shell session'); + return false; } return $this->_send_channel_packet($this->_get_interactive_channel(), $cmd); @@ -2734,9 +2736,9 @@ class SSH2 * returns that and then that that was passed into stopSubsystem() but that'll be saved for a future date and implemented * if there's sufficient demand for such a feature. * - * @see self::stopSubsystem() - * @param string $subsystem - * @return bool + * @see \phpseclib\Net\SSH2::stopSubsystem() + * @param String $subsystem + * @return Boolean * @access public */ function startSubsystem($subsystem) @@ -2797,8 +2799,8 @@ class SSH2 /** * Stops a subsystem. * - * @see self::startSubsystem() - * @return bool + * @see \phpseclib\Net\SSH2::startSubsystem() + * @return Boolean * @access public */ function stopSubsystem() @@ -2843,7 +2845,6 @@ class SSH2 if (isset($this->realtime_log_file) && is_resource($this->realtime_log_file)) { fclose($this->realtime_log_file); } - unset(self::$connections[$this->getResourceId()]); } /** @@ -2862,7 +2863,7 @@ class SSH2 /** * Is the connection still active? * - * @return bool + * @return boolean * @access public */ function isConnected() @@ -2870,32 +2871,21 @@ class SSH2 return (bool) ($this->bitmap & self::MASK_CONNECTED); } - /** - * Have you successfully been logged in? - * - * @return bool - * @access public - */ - function isAuthenticated() - { - return (bool) ($this->bitmap & self::MASK_LOGIN); - } - /** * Gets Binary Packets * * See '6. Binary Packet Protocol' of rfc4253 for more info. * - * @see self::_send_binary_packet() - * @return string - * @throws \RuntimeException on connection errors + * @see \phpseclib\Net\SSH2::_send_binary_packet() + * @return String * @access private */ function _get_binary_packet() { if (!is_resource($this->fsock) || feof($this->fsock)) { + user_error('Connection closed prematurely'); $this->bitmap = 0; - throw new \RuntimeException('Connection closed prematurely'); + return false; } $start = microtime(true); @@ -2909,7 +2899,8 @@ class SSH2 $raw = $this->decrypt->decrypt($raw); } if ($raw === false) { - throw new \RuntimeException('Unable to decrypt content'); + user_error('Unable to decrypt content'); + return false; } extract(unpack('Npacket_length/Cpadding_length', $this->_string_shift($raw, 5))); @@ -2920,15 +2911,17 @@ class SSH2 // "implementations SHOULD check that the packet length is reasonable" // PuTTY uses 0x9000 as the actual max packet size and so to shall we if ($remaining_length < -$this->decrypt_block_size || $remaining_length > 0x9000 || $remaining_length % $this->decrypt_block_size != 0) { - throw new \RuntimeException('Invalid size'); + user_error('Invalid size'); + return false; } $buffer = ''; while ($remaining_length > 0) { $temp = fread($this->fsock, $remaining_length); if ($temp === false || feof($this->fsock)) { + user_error('Error reading from socket'); $this->bitmap = 0; - throw new \RuntimeException('Error reading from socket'); + return false; } $buffer.= $temp; $remaining_length-= strlen($temp); @@ -2944,10 +2937,12 @@ class SSH2 if ($this->hmac_check !== false) { $hmac = fread($this->fsock, $this->hmac_size); if ($hmac === false || strlen($hmac) != $this->hmac_size) { + user_error('Error reading socket'); $this->bitmap = 0; - throw new \RuntimeException('Error reading socket'); + return false; } elseif ($hmac != $this->hmac_check->hash(pack('NNCa*', $this->get_seq_no, $packet_length, $padding_length, $payload . $padding))) { - throw new \RuntimeException('Invalid HMAC'); + user_error('Invalid HMAC'); + return false; } } @@ -2974,8 +2969,8 @@ class SSH2 * * Because some binary packets need to be ignored... * - * @see self::_get_binary_packet() - * @return string + * @see \phpseclib\Net\SSH2::_get_binary_packet() + * @return String * @access private */ function _filter($payload) @@ -3123,10 +3118,11 @@ class SSH2 /** * Returns whether Quiet Mode is enabled or not * - * @see self::enableQuietMode() - * @see self::disableQuietMode() + * @see \phpseclib\Net\SSH2::enableQuietMode() + * @see \phpseclib\Net\SSH2::disableQuietMode() + * * @access public - * @return bool + * @return boolean */ function isQuietModeEnabled() { @@ -3156,10 +3152,11 @@ class SSH2 /** * Returns whether request-pty is enabled or not * - * @see self::enablePTY() - * @see self::disablePTY() + * @see \phpseclib\Net\SSH2::enablePTY() + * @see \phpseclib\Net\SSH2::disablePTY() + * * @access public - * @return bool + * @return boolean */ function isPTYEnabled() { @@ -3172,8 +3169,7 @@ class SSH2 * Returns the data as a string if it's available and false if not. * * @param $client_channel - * @return mixed - * @throws \RuntimeException on connection error + * @return Mixed * @access private */ function _get_channel_packet($client_channel, $skip_extended = false) @@ -3206,7 +3202,8 @@ class SSH2 $response = $this->_get_binary_packet(); if ($response === false) { - throw new \RuntimeException('Connection closed by server'); + user_error('Connection closed by server'); + return false; } if ($client_channel == -1 && $response === true) { return true; @@ -3255,8 +3252,8 @@ class SSH2 return $result; //case NET_SSH2_MSG_CHANNEL_OPEN_FAILURE: default: - $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); - throw new \RuntimeException('Unable to open channel'); + user_error('Unable to open channel'); + return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); } break; case NET_SSH2_MSG_CHANNEL_REQUEST: @@ -3266,8 +3263,8 @@ class SSH2 case NET_SSH2_MSG_CHANNEL_FAILURE: return false; default: - $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); - throw new \RuntimeException('Unable to fulfill channel request'); + user_error('Unable to fulfill channel request'); + return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); } case NET_SSH2_MSG_CHANNEL_CLOSE: return $type == NET_SSH2_MSG_CHANNEL_CLOSE ? true : $this->_get_channel_packet($client_channel, $skip_extended); @@ -3376,8 +3373,8 @@ class SSH2 case NET_SSH2_MSG_CHANNEL_EOF: break; default: - $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); - throw new \RuntimeException('Error reading channel data'); + user_error('Error reading channel data'); + return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); } } } @@ -3387,17 +3384,18 @@ class SSH2 * * See '6. Binary Packet Protocol' of rfc4253 for more info. * - * @param string $data - * @param string $logged - * @see self::_get_binary_packet() - * @return bool + * @param String $data + * @param optional String $logged + * @see \phpseclib\Net\SSH2::_get_binary_packet() + * @return Boolean * @access private */ function _send_binary_packet($data, $logged = null) { if (!is_resource($this->fsock) || feof($this->fsock)) { + user_error('Connection closed prematurely'); $this->bitmap = 0; - throw new \RuntimeException('Connection closed prematurely'); + return false; } //if ($this->compress) { @@ -3447,7 +3445,7 @@ class SSH2 * * Makes sure that only the last 1MB worth of packets will be logged * - * @param string $data + * @param String $data * @access private */ function _append_log($message_number, $message) @@ -3523,9 +3521,9 @@ class SSH2 * * Spans multiple SSH_MSG_CHANNEL_DATAs if appropriate * - * @param int $client_channel - * @param string $data - * @return bool + * @param Integer $client_channel + * @param String $data + * @return Boolean * @access private */ function _send_channel_packet($client_channel, $data) @@ -3571,9 +3569,9 @@ class SSH2 * and for SFTP channels are presumably closed when the client disconnects. This functions is intended * for SCP more than anything. * - * @param int $client_channel - * @param bool $want_reply - * @return bool + * @param Integer $client_channel + * @param Boolean $want_reply + * @return Boolean * @access private */ function _close_channel($client_channel, $want_reply = false) @@ -3605,8 +3603,8 @@ class SSH2 /** * Disconnect * - * @param int $reason - * @return bool + * @param Integer $reason + * @return Boolean * @access private */ function _disconnect($reason) @@ -3625,9 +3623,9 @@ class SSH2 * * Inspired by array_shift * - * @param string $string - * @param int $index - * @return string + * @param String $string + * @param optional Integer $index + * @return String * @access private */ function _string_shift(&$string, $index = 1) @@ -3644,7 +3642,7 @@ class SSH2 * named constants from it, using the value as the name of the constant and the index as the value of the constant. * If any of the constants that would be defined already exists, none of the constants will be defined. * - * @param array $array + * @param Array $array * @access private */ function _define_array() @@ -3667,7 +3665,7 @@ class SSH2 * Returns a string if NET_SSH2_LOGGING == self::LOG_COMPLEX, an array if NET_SSH2_LOGGING == self::LOG_SIMPLE and false if !defined('NET_SSH2_LOGGING') * * @access public - * @return array|false|string + * @return String or Array */ function getLog() { @@ -3690,10 +3688,10 @@ class SSH2 /** * Formats a log for printing * - * @param array $message_log - * @param array $message_number_log + * @param Array $message_log + * @param Array $message_number_log * @access private - * @return string + * @return String */ function _format_log($message_log, $message_number_log) { @@ -3726,9 +3724,9 @@ class SSH2 * * For use with preg_replace_callback() * - * @param array $matches + * @param Array $matches * @access private - * @return string + * @return String */ function _format_log_helper($matches) { @@ -3755,9 +3753,9 @@ class SSH2 * Returns the first value of the intersection of two arrays or false if * the intersection is empty. The order is defined by the first parameter. * - * @param array $array1 - * @param array $array2 - * @return mixed False if intersection is empty, else intersected value. + * @param Array $array1 + * @param Array $array2 + * @return Mixed False if intersection is empty, else intersected value. * @access private */ function _array_intersect_first($array1, $array2) @@ -3773,7 +3771,7 @@ class SSH2 /** * Returns all errors * - * @return string + * @return String * @access public */ function getErrors() @@ -3784,22 +3782,18 @@ class SSH2 /** * Returns the last error * - * @return string + * @return String * @access public */ function getLastError() { - $count = count($this->errors); - - if ($count > 0) { - return $this->errors[$count - 1]; - } + return $this->errors[count($this->errors) - 1]; } /** * Return the server identification. * - * @return string + * @return String * @access public */ function getServerIdentification() @@ -3812,7 +3806,7 @@ class SSH2 /** * Return a list of the key exchange algorithms the server supports. * - * @return array + * @return Array * @access public */ function getKexAlgorithms() @@ -3825,7 +3819,7 @@ class SSH2 /** * Return a list of the host key (public key) algorithms the server supports. * - * @return array + * @return Array * @access public */ function getServerHostKeyAlgorithms() @@ -3838,7 +3832,7 @@ class SSH2 /** * Return a list of the (symmetric key) encryption algorithms the server supports, when receiving stuff from the client. * - * @return array + * @return Array * @access public */ function getEncryptionAlgorithmsClient2Server() @@ -3851,7 +3845,7 @@ class SSH2 /** * Return a list of the (symmetric key) encryption algorithms the server supports, when sending stuff to the client. * - * @return array + * @return Array * @access public */ function getEncryptionAlgorithmsServer2Client() @@ -3864,7 +3858,7 @@ class SSH2 /** * Return a list of the MAC algorithms the server supports, when receiving stuff from the client. * - * @return array + * @return Array * @access public */ function getMACAlgorithmsClient2Server() @@ -3877,7 +3871,7 @@ class SSH2 /** * Return a list of the MAC algorithms the server supports, when sending stuff to the client. * - * @return array + * @return Array * @access public */ function getMACAlgorithmsServer2Client() @@ -3890,7 +3884,7 @@ class SSH2 /** * Return a list of the compression algorithms the server supports, when receiving stuff from the client. * - * @return array + * @return Array * @access public */ function getCompressionAlgorithmsClient2Server() @@ -3903,7 +3897,7 @@ class SSH2 /** * Return a list of the compression algorithms the server supports, when sending stuff to the client. * - * @return array + * @return Array * @access public */ function getCompressionAlgorithmsServer2Client() @@ -3916,7 +3910,7 @@ class SSH2 /** * Return a list of the languages the server supports, when sending stuff to the client. * - * @return array + * @return Array * @access public */ function getLanguagesServer2Client() @@ -3929,7 +3923,7 @@ class SSH2 /** * Return a list of the languages the server supports, when receiving stuff from the client. * - * @return array + * @return Array * @access public */ function getLanguagesClient2Server() @@ -3945,7 +3939,7 @@ class SSH2 * Quoting from the RFC, "in some jurisdictions, sending a warning message before * authentication may be relevant for getting legal protection." * - * @return string + * @return String * @access public */ function getBannerMessage() @@ -3959,9 +3953,7 @@ class SSH2 * Caching this the first time you connect to a server and checking the result on subsequent connections * is recommended. Returns false if the server signature is not signed correctly with the public host key. * - * @return mixed - * @throws \RuntimeException on badly formatted keys - * @throws \phpseclib\Exception\NoSupportedAlgorithmsException when the key isn't in a supported format + * @return Mixed * @access public */ function getServerPublicHostKey() @@ -4007,8 +3999,8 @@ class SSH2 padding, unsigned, and in network byte order). */ $temp = unpack('Nlength', $this->_string_shift($signature, 4)); if ($temp['length'] != 40) { - $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new \RuntimeException('Invalid signature'); + user_error('Invalid signature'); + return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); } $r = new BigInteger($this->_string_shift($signature, 20), 256); @@ -4019,8 +4011,8 @@ class SSH2 case $r->compare($q) >= 0: case $s->equals($zero): case $s->compare($q) >= 0: - $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new \RuntimeException('Invalid signature'); + user_error('Invalid signature'); + return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); } $w = $s->modInverse($q); @@ -4039,7 +4031,7 @@ class SSH2 list(, $v) = $v->divide($q); if (!$v->equals($r)) { - //user_error('Bad server signature'); + user_error('Bad server signature'); return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE); } @@ -4058,10 +4050,10 @@ class SSH2 $signature = $this->_string_shift($signature, $temp['length']); $rsa = new RSA(); - $rsa->load(array('e' => $e, 'n' => $n), 'raw'); - $rsa->setHash('sha1'); - if (!$rsa->verify($this->exchange_hash, $signature, RSA::PADDING_PKCS1)) { - //user_error('Bad server signature'); + $rsa->setSignatureMode(RSA::SIGNATURE_PKCS1); + $rsa->loadKey(array('e' => $e, 'n' => $n), RSA::PUBLIC_FORMAT_RAW); + if (!$rsa->verify($this->exchange_hash, $signature)) { + user_error('Bad server signature'); return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE); } */ @@ -4076,8 +4068,8 @@ class SSH2 // also, see SSHRSA.c (rsa2_verifysig) in PuTTy's source. if ($s->compare(new BigInteger()) < 0 || $s->compare($n->subtract(new BigInteger(1))) > 0) { - $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); - throw new \RuntimeException('Invalid signature'); + user_error('Invalid signature'); + return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED); } $s = $s->modPow($e, $n); @@ -4087,13 +4079,13 @@ class SSH2 $h = chr(0x01) . str_repeat(chr(0xFF), $nLength - 2 - strlen($h)) . $h; if ($s != $h) { - //user_error('Bad server signature'); + user_error('Bad server signature'); return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE); } break; default: - $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE); - throw new NoSupportedAlgorithmsException('Unsupported signature format'); + user_error('Unsupported signature format'); + return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE); } return $this->signature_format . ' ' . base64_encode($this->server_public_host_key); @@ -4102,7 +4094,7 @@ class SSH2 /** * Returns the exit status of an SSH command or false. * - * @return false|int + * @return Integer or false * @access public */ function getExitStatus() @@ -4116,7 +4108,7 @@ class SSH2 /** * Returns the number of columns for the terminal window size. * - * @return int + * @return Integer * @access public */ function getWindowColumns() @@ -4127,7 +4119,7 @@ class SSH2 /** * Returns the number of rows for the terminal window size. * - * @return int + * @return Integer * @access public */ function getWindowRows() @@ -4138,7 +4130,7 @@ class SSH2 /** * Sets the number of columns for the terminal window size. * - * @param int $value + * @param Integer $value * @access public */ function setWindowColumns($value) @@ -4149,7 +4141,7 @@ class SSH2 /** * Sets the number of rows for the terminal window size. * - * @param int $value + * @param Integer $value * @access public */ function setWindowRows($value) @@ -4160,8 +4152,8 @@ class SSH2 /** * Sets the number of columns and rows for the terminal window size. * - * @param int $columns - * @param int $rows + * @param Integer $columns + * @param Integer $rows * @access public */ function setWindowSize($columns = 80, $rows = 24) @@ -4169,47 +4161,4 @@ class SSH2 $this->windowColumns = $columns; $this->windowRows = $rows; } - - /** - * @return string - */ - function __toString() - { - return $this->getResourceId(); - } - - /** - * We use {} because that symbols should not be in URL according to - * {@link http://tools.ietf.org/html/rfc3986#section-2 RFC}. - * It will safe us from any conflicts, because otherwise regexp will - * match all alphanumeric domains. - * - * @return string - */ - function getResourceId() - { - return '{' . spl_object_hash($this) . '}'; - } - - /** - * Return existing connection - * - * @param string $id - * - * @return bool|SSH2 will return false if no such connection - */ - static function getConnectionByResourceId($id) - { - return isset(self::$connections[$id]) ? self::$connections[$id] : false; - } - - /** - * Return all excising connections - * - * @return SSH2[] - */ - static function getConnections() - { - return self::$connections; - } } diff --git a/phpseclib/System/SSH/Agent.php b/phpseclib/System/SSH/Agent.php index a4dad183..4cb9dec0 100644 --- a/phpseclib/System/SSH/Agent.php +++ b/phpseclib/System/SSH/Agent.php @@ -34,7 +34,6 @@ namespace phpseclib\System\SSH; use phpseclib\Crypt\RSA; -use phpseclib\Exception\BadConfigurationException; use phpseclib\System\SSH\Agent\Identity; /** @@ -84,7 +83,7 @@ class Agent /** * Socket Resource * - * @var resource + * @var Resource * @access private */ var $fsock; @@ -116,8 +115,6 @@ 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() @@ -130,12 +127,13 @@ class Agent $address = $_ENV['SSH_AUTH_SOCK']; break; default: - throw new \BadConfigurationException('SSH_AUTH_SOCK not found'); + user_error('SSH_AUTH_SOCK not found'); + return false; } $this->fsock = fsockopen('unix://' . $address, 0, $errno, $errstr); if (!$this->fsock) { - throw new \RuntimeException("Unable to connect to ssh-agent (Error $errno: $errstr)"); + user_error("Unable to connect to ssh-agent (Error $errno: $errstr)"); } } @@ -145,8 +143,7 @@ class Agent * See "2.5.2 Requesting a list of protocol 2 keys" * Returns an array containing zero or more \phpseclib\System\SSH\Agent\Identity objects * - * @return array - * @throws \RuntimeException on receipt of unexpected packets + * @return Array * @access public */ function requestIdentities() @@ -157,13 +154,13 @@ class Agent $packet = pack('NC', 1, self::SSH_AGENTC_REQUEST_IDENTITIES); if (strlen($packet) != fputs($this->fsock, $packet)) { - throw new \RuntimeException('Connection closed while requesting identities'); + user_error('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) { - throw new \RuntimeException('Unable to request identities'); + user_error('Unable to request identities'); } $identities = array(); @@ -172,15 +169,13 @@ class Agent $length = current(unpack('N', fread($this->fsock, 4))); $key_blob = fread($this->fsock, $length); $length = current(unpack('N', fread($this->fsock, 4))); - if ($length) { - $key_comment = fread($this->fsock, $length); - } + $key_comment = fread($this->fsock, $length); $length = current(unpack('N', substr($key_blob, 0, 4))); $key_type = substr($key_blob, 4, $length); switch ($key_type) { case 'ssh-rsa': $key = new RSA(); - $key->load('ssh-rsa ' . base64_encode($key_blob) . ' ' . $key_comment); + $key->loadKey('ssh-rsa ' . base64_encode($key_blob) . ' ' . $key_comment); break; case 'ssh-dss': // not currently supported @@ -204,7 +199,7 @@ class Agent * be requested when a channel is opened * * @param Net_SSH2 $ssh - * @return bool + * @return Boolean * @access public */ function startSSHForwarding($ssh) @@ -218,7 +213,7 @@ class Agent * Request agent forwarding of remote server * * @param Net_SSH2 $ssh - * @return bool + * @return Boolean * @access private */ function _request_forwarding($ssh) @@ -274,9 +269,8 @@ class Agent /** * Forward data to SSH Agent and return data reply * - * @param string $data + * @param String $data * @return data from SSH Agent - * @throws \RuntimeException on connection errors * @access private */ function _forward_data($data) @@ -295,7 +289,7 @@ class Agent } if (strlen($this->socket_buffer) != fwrite($this->fsock, $this->socket_buffer)) { - throw new \RuntimeException('Connection closed attempting to forward data to SSH agent'); + user_error('Connection closed attempting to forward data to SSH agent'); } $this->socket_buffer = ''; diff --git a/phpseclib/System/SSH/Agent/Identity.php b/phpseclib/System/SSH/Agent/Identity.php index 612c414e..490edf6e 100644 --- a/phpseclib/System/SSH/Agent/Identity.php +++ b/phpseclib/System/SSH/Agent/Identity.php @@ -15,8 +15,6 @@ namespace phpseclib\System\SSH\Agent; -use phpseclib\Crypt\RSA; -use phpseclib\Exception\UnsupportedAlgorithmException; use phpseclib\System\SSH\Agent; /** @@ -25,8 +23,9 @@ use phpseclib\System\SSH\Agent; * Instantiation should only be performed by \phpseclib\System\SSH\Agent class. * This could be thought of as implementing an interface that phpseclib\Crypt\RSA * implements. ie. maybe a Net_SSH_Auth_PublicKey interface or something. - * The methods in this interface would be getPublicKey and sign since those are the - * methods phpseclib looks for to perform public key authentication. + * The methods in this interface would be getPublicKey, setSignatureMode + * and sign since those are the methods phpseclib looks for to perform + * public key authentication. * * @package SSH\Agent * @author Jim Wigginton @@ -39,32 +38,32 @@ class Identity * * @var \phpseclib\Crypt\RSA * @access private - * @see self::getPublicKey() + * @see \phpseclib\System\SSH\Agent\Identity::getPublicKey() */ var $key; /** * Key Blob * - * @var string + * @var String * @access private - * @see self::sign() + * @see \phpseclib\System\SSH\Agent\Identity::sign() */ var $key_blob; /** * Socket Resource * - * @var resource + * @var Resource * @access private - * @see self::sign() + * @see \phpseclib\System\SSH\Agent\Identity::sign() */ var $fsock; /** * Default Constructor. * - * @param resource $fsock + * @param Resource $fsock * @return \phpseclib\System\SSH\Agent\Identity * @access private */ @@ -93,7 +92,7 @@ class Identity * Called by \phpseclib\System\SSH\Agent::requestIdentities(). The key blob could be extracted from $this->key * but this saves a small amount of computation. * - * @param string $key_blob + * @param String $key_blob * @access private */ function setPublicKeyBlob($key_blob) @@ -106,29 +105,26 @@ class Identity * * Wrapper for $this->key->getPublicKey() * - * @param int $type optional - * @return mixed + * @param Integer $format optional + * @return Mixed * @access public */ - function getPublicKey($type = 'PKCS8') + function getPublicKey($format = null) { - return $this->key->getPublicKey($type); + return !isset($format) ? $this->key->getPublicKey() : $this->key->getPublicKey($format); } /** - * Sets the hash + * Set Signature Mode * - * ssh-agent only supports signatures with sha1 hashes but to maintain BC with RSA.php this function exists + * Doesn't do anything as ssh-agent doesn't let you pick and choose the signature mode. ie. + * ssh-agent's only supported mode is \phpseclib\Crypt\RSA::SIGNATURE_PKCS1 * - * @param string $hash optional - * @throws \phpseclib\Exception\UnsupportedAlgorithmException if the algorithm is unsupported + * @param Integer $mode * @access public */ - function setHash($hash = 'sha1') + function setSignatureMode($mode) { - if ($hash != 'sha1') { - throw new UnsupportedAlgorithmException('ssh-agent can only be used with the sha1 hash'); - } } /** @@ -136,30 +132,23 @@ 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 + * @param String $message + * @return String * @access public */ - function sign($message, $padding = RSA::PADDING_PKCS1) + function sign($message) { - 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, 0); $packet = pack('Na*', strlen($packet), $packet); if (strlen($packet) != fputs($this->fsock, $packet)) { - throw new \RuntimeException('Connection closed during signing'); + user_error('Connection closed during signing'); } $length = current(unpack('N', fread($this->fsock, 4))); $type = ord(fread($this->fsock, 1)); if ($type != Agent::SSH_AGENT_SIGN_RESPONSE) { - throw new \RuntimeException('Unable to retreive signature'); + user_error('Unable to retreive signature'); } $signature_blob = fread($this->fsock, $length - 1); diff --git a/tests/Functional/Net/SFTPStreamTest.php b/tests/Functional/Net/SFTPStreamTest.php index 83602359..b596c4f8 100644 --- a/tests/Functional/Net/SFTPStreamTest.php +++ b/tests/Functional/Net/SFTPStreamTest.php @@ -27,34 +27,6 @@ class Functional_Net_SFTPStreamTest extends Functional_Net_SFTPTestCase $this->assertSame(0, $this->sftp->size('fooo.txt')); } - /** - * @group github778 - */ - public function testFilenameWithHash() - { - $context = stream_context_create(array( - 'sftp' => array('session' => $this->sftp), - )); - $fp = fopen($this->buildUrl('te#st.txt'), 'wb', false, $context); - fputs($fp, 'zzzz'); - fclose($fp); - - $this->assertTrue(in_array('te#st.txt', $this->sftp->nlist())); - } - - /** - * Tests connection reuse functionality same as ssh2 extension: - * {@link http://php.net/manual/en/wrappers.ssh2.php#refsect1-wrappers.ssh2-examples} - */ - public function testConnectionReuse() - { - $originalConnectionsCount = count(\phpseclib\Net\SSH2::getConnections()); - $session = $this->sftp; - $dirs = scandir("sftp://$session/"); - $this->assertCount($originalConnectionsCount, \phpseclib\Net\SSH2::getConnections()); - $this->assertEquals(array('.', '..'), array_slice($dirs, 0, 2)); - } - protected function buildUrl($suffix) { return sprintf( diff --git a/tests/Functional/Net/SFTPTestCase.php b/tests/Functional/Net/SFTPTestCase.php index aec75e71..abd5999d 100644 --- a/tests/Functional/Net/SFTPTestCase.php +++ b/tests/Functional/Net/SFTPTestCase.php @@ -13,9 +13,6 @@ use phpseclib\Net\SFTP; */ abstract class Functional_Net_SFTPTestCase extends PhpseclibFunctionalTestCase { - /** - * @var SFTP - */ protected $sftp; protected $scratchDir; diff --git a/tests/Functional/Net/SFTPUserStoryTest.php b/tests/Functional/Net/SFTPUserStoryTest.php index 963ead41..57102ecb 100644 --- a/tests/Functional/Net/SFTPUserStoryTest.php +++ b/tests/Functional/Net/SFTPUserStoryTest.php @@ -171,8 +171,8 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase } /** - * @depends testStatOnDir - */ + * @depends testStatOnDir + */ public function testPutSizeGetFileCallback($sftp) { self::$buffer = self::$exampleData; @@ -240,20 +240,6 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase /** * @depends testTruncate - * @group github850 - */ - public function testChModOnFile($sftp) - { - $this->assertNotFalse( - $sftp->chmod(0755, 'file1.txt'), - 'Failed asserting that chmod() was successful.' - ); - - return $sftp; - } - - /** - * @depends testChModOnFile */ public function testChDirOnFile($sftp) { @@ -665,28 +651,5 @@ class Functional_Net_SFTPUserStoryTest extends PhpseclibFunctionalTestCase $this->assertSame($stat['type'], NET_SFTP_TYPE_SYMLINK); $sftp->enableStatCache(); - - return $sftp; - } - - /** - * @depends testStatVsLstat - * @group github830 - */ - public function testUploadOffsets($sftp) - { - $sftp->put('offset.txt', 'res.txt', SFTP::SOURCE_LOCAL_FILE, 0, 10); - $this->assertSame( - substr(self::$exampleData, 10), - $sftp->get('offset.txt'), - 'Failed asserting that portions of a file could be uploaded.' - ); - - $sftp->put('offset.txt', 'res.txt', SFTP::SOURCE_LOCAL_FILE, self::$exampleDataLength - 100); - $this->assertSame( - substr(self::$exampleData, 10, -90) . self::$exampleData, - $sftp->get('offset.txt'), - 'Failed asserting that you could upload into the middle of a file.' - ); } } diff --git a/tests/Functional/Net/SSH2Test.php b/tests/Functional/Net/SSH2Test.php index 4c18abed..51373705 100644 --- a/tests/Functional/Net/SSH2Test.php +++ b/tests/Functional/Net/SSH2Test.php @@ -34,11 +34,6 @@ class Functional_Net_SSH2Test extends PhpseclibFunctionalTestCase 'Failed asserting that SSH2 is not connected after construction.' ); - $this->assertFalse( - $ssh->isAuthenticated(), - 'Failed asserting that SSH2 is not authenticated after construction.' - ); - $this->assertNotEmpty( $ssh->getServerPublicHostKey(), 'Failed asserting that a non-empty public host key was fetched.' @@ -60,31 +55,6 @@ class Functional_Net_SSH2Test extends PhpseclibFunctionalTestCase /** * @depends testPreLogin */ - public function testBadPassword($ssh) - { - $username = $this->getEnv('SSH_USERNAME'); - $password = $this->getEnv('SSH_PASSWORD'); - $this->assertFalse( - $ssh->login($username, 'zzz' . $password), - 'SSH2 login using password succeeded.' - ); - - $this->assertTrue( - $ssh->isConnected(), - 'Failed asserting that SSH2 is connected after bad login attempt.' - ); - - $this->assertFalse( - $ssh->isAuthenticated(), - 'Failed asserting that SSH2 is not authenticated after bad login attempt.' - ); - - return $ssh; - } - - /** - * @depends testBadPassword - */ public function testPasswordLogin($ssh) { $username = $this->getEnv('SSH_USERNAME'); @@ -94,11 +64,6 @@ class Functional_Net_SSH2Test extends PhpseclibFunctionalTestCase 'SSH2 login using password failed.' ); - $this->assertTrue( - $ssh->isAuthenticated(), - 'Failed asserting that SSH2 is authenticated after good login attempt.' - ); - return $ssh; } diff --git a/tests/PhpseclibFunctionalTestCase.php b/tests/PhpseclibFunctionalTestCase.php index ba646edb..e0b3a7cf 100644 --- a/tests/PhpseclibFunctionalTestCase.php +++ b/tests/PhpseclibFunctionalTestCase.php @@ -28,7 +28,9 @@ abstract class PhpseclibFunctionalTestCase extends PhpseclibTestCase 'Should have gmp or bcmath extension for functional test.' ); } + self::ensureConstant('CRYPT_HASH_MODE', Hash::MODE_HASH); self::reRequireFile('Math/BigInteger.php'); + self::reRequireFile('Crypt/Hash.php'); } parent::setUpBeforeClass(); } diff --git a/tests/PhpseclibTestCase.php b/tests/PhpseclibTestCase.php index 1a2a8e4a..4dc28b9a 100644 --- a/tests/PhpseclibTestCase.php +++ b/tests/PhpseclibTestCase.php @@ -59,7 +59,7 @@ abstract class PhpseclibTestCase extends PHPUnit_Framework_TestCase $value = constant($constant); if ($value !== $expected) { - if (extension_loaded('runkit')) { + if (function_exists('runkit_constant_redefine')) { if (!runkit_constant_redefine($constant, $expected)) { self::markTestSkipped(sprintf( "Failed to redefine constant %s to %s", @@ -82,15 +82,15 @@ abstract class PhpseclibTestCase extends PHPUnit_Framework_TestCase } /** - * @param string $filename Filename relative to library directory. + * @param string $filename * * @return null */ protected static function reRequireFile($filename) { - if (extension_loaded('runkit')) { + if (function_exists('runkit_import')) { $result = runkit_import( - sprintf('%s/../phpseclib/%s', __DIR__, $filename), + $filename, RUNKIT_IMPORT_FUNCTIONS | RUNKIT_IMPORT_CLASS_METHODS | RUNKIT_IMPORT_OVERRIDE diff --git a/tests/Unit/Crypt/AES/TestCase.php b/tests/Unit/Crypt/AES/TestCase.php index d89516ea..2f251b50 100644 --- a/tests/Unit/Crypt/AES/TestCase.php +++ b/tests/Unit/Crypt/AES/TestCase.php @@ -47,26 +47,24 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase ':-):-):-):-):-):-)', // https://github.com/phpseclib/phpseclib/pull/43 ); $ivs = array( - str_repeat("\0", 16), - str_pad('test123', 16, "\0"), + '', + 'test123', ); $keys = array( - str_repeat("\0", 16), - str_pad(':-8', 16, "\0"), // https://github.com/phpseclib/phpseclib/pull/43 - str_pad('FOOBARZ', 16, "\0"), + '', + ':-8', // https://github.com/phpseclib/phpseclib/pull/43 + 'FOOBARZ', ); $result = array(); - foreach ($modes as $mode) { - foreach ($plaintexts as $plaintext) { - foreach ($ivs as $iv) { - foreach ($keys as $key) { - $result[] = array($mode, $plaintext, $iv, $key); - } - } - } - } + // @codingStandardsIgnoreStart + foreach ($modes as $mode) + foreach ($plaintexts as $plaintext) + foreach ($ivs as $iv) + foreach ($keys as $key) + $result[] = array($mode, $plaintext, $iv, $key); + // @codingStandardsIgnoreEnd return $result; } @@ -100,11 +98,10 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase // this test case is from the following URL: // https://web.archive.org/web/20070209120224/http://fp.gladman.plus.com/cryptography_technology/rijndael/aesdvec.zip - $aes = new Rijndael(Base::MODE_CBC); + $aes = new Rijndael(); $aes->setPreferredEngine($this->engine); $aes->disablePadding(); $aes->setKey(pack('H*', '2b7e151628aed2a6abf7158809cf4f3c762e7160')); // 160-bit key. Valid in Rijndael. - $aes->setIV(str_repeat("\0", 16)); //$this->_checkEngine($aes); // should only work in internal mode $ciphertext = $aes->encrypt(pack('H*', '3243f6a8885a308d313198a2e0370734')); $this->assertEquals($ciphertext, pack('H*', '231d844639b31b412211cfe93712b880')); @@ -112,27 +109,25 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase /** * @group github451 - * @expectedException \LengthException */ public function testKeyPaddingAES() { // same as the above - just with a different ciphertext - $aes = new AES(Base::MODE_CBC); + $aes = new AES(); $aes->setPreferredEngine($this->engine); $aes->disablePadding(); - $aes->setKey(pack('H*', '2b7e151628aed2a6abf7158809cf4f3c762e7160')); // 160-bit key. supported by Rijndael - not AES - $aes->setIV(str_repeat("\0", 16)); + $aes->setKey(pack('H*', '2b7e151628aed2a6abf7158809cf4f3c762e7160')); // 160-bit key. AES should null pad to 192-bits $this->_checkEngine($aes); $ciphertext = $aes->encrypt(pack('H*', '3243f6a8885a308d313198a2e0370734')); $this->assertEquals($ciphertext, pack('H*', 'c109292b173f841b88e0ee49f13db8c0')); } /** - * Produces all combinations of test values. - * - * @return array - */ + * Produces all combinations of test values. + * + * @return array + */ public function continuousBufferBatteryCombos() { $modes = array( @@ -160,20 +155,19 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase $result = array(); - foreach ($modes as $mode) { - foreach ($combos as $combo) { - foreach (array('encrypt', 'decrypt') as $op) { - $result[] = array($op, $mode, $combo); - } - } - } + // @codingStandardsIgnoreStart + foreach ($modes as $mode) + foreach ($combos as $combo) + foreach (array('encrypt', 'decrypt') as $op) + $result[] = array($op, $mode, $combo); + // @codingStandardsIgnoreEnd return $result; } /** - * @dataProvider continuousBufferBatteryCombos - */ + * @dataProvider continuousBufferBatteryCombos + */ public function testContinuousBufferBattery($op, $mode, $test) { $iv = str_repeat('x', 16); @@ -217,10 +211,9 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase } /** - * Pretty much the same as testContinuousBufferBattery with the caveat that continuous mode is not enabled. - * - * @dataProvider continuousBufferBatteryCombos - */ + * @dataProvider continuousBufferBatteryCombos + */ + // pretty much the same as testContinuousBufferBattery with the caveat that continuous mode is not enabled public function testNonContinuousBufferBattery($op, $mode, $test) { if (count($test) == 1) { @@ -267,7 +260,7 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase // from http://csrc.nist.gov/groups/STM/cavp/documents/aes/AESAVS.pdf#page=16 public function testGFSBox128() { - $aes = new AES(Base::MODE_CBC); + $aes = new AES(); $aes->setKey(pack('H*', '00000000000000000000000000000000')); $aes->setIV(pack('H*', '00000000000000000000000000000000')); @@ -294,7 +287,7 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase public function testGFSBox192() { - $aes = new AES(Base::MODE_CBC); + $aes = new AES(); $aes->setKey(pack('H*', '000000000000000000000000000000000000000000000000')); $aes->setIV(pack('H*', '00000000000000000000000000000000')); @@ -319,7 +312,7 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase public function testGFSBox256() { - $aes = new AES(Base::MODE_CBC); + $aes = new AES(); $aes->setKey(pack('H*', '00000000000000000000000000000000' . '00000000000000000000000000000000')); $aes->setIV(pack('H*', '00000000000000000000000000000000')); @@ -339,63 +332,4 @@ abstract class Unit_Crypt_AES_TestCase extends PhpseclibTestCase $result = bin2hex($aes->encrypt(pack('H*', '91fbef2d15a97816060bee1feaa49afe'))); $this->assertSame($result, '1bc704f1bce135ceb810341b216d7abe'); } - - public function testGetKeyLengthDefault() - { - $aes = new AES(Base::MODE_CBC); - $this->assertSame($aes->getKeyLength(), 128); - } - - public function testGetKeyLengthWith192BitKey() - { - $aes = new AES(Base::MODE_CBC); - $aes->setKey(str_repeat('a', 24)); - $this->assertSame($aes->getKeyLength(), 192); - } - - /** - * @expectedException \LengthException - */ - public function testSetKeyLengthWithLargerKey() - { - $aes = new AES(Base::MODE_CBC); - $aes->setKeyLength(128); - $aes->setKey(str_repeat('a', 24)); - $aes->setIV(str_repeat("\0", 16)); - $this->assertSame($aes->getKeyLength(), 128); - $ciphertext = bin2hex($aes->encrypt('a')); - $this->assertSame($ciphertext, '82b7b068dfc60ed2a46893b69fecd6c2'); - $this->assertSame($aes->getKeyLength(), 128); - } - - /** - * @expectedException \LengthException - */ - public function testSetKeyLengthWithSmallerKey() - { - $aes = new AES(Base::MODE_CBC); - $aes->setKeyLength(256); - $aes->setKey(str_repeat('a', 16)); - $aes->setIV(str_repeat("\0", 16)); - $this->assertSame($aes->getKeyLength(), 256); - $ciphertext = bin2hex($aes->encrypt('a')); - $this->assertSame($ciphertext, 'fd4250c0d234aa7e1aa592820aa8406b'); - $this->assertSame($aes->getKeyLength(), 256); - } - - /** - * @group github938 - */ - public function testContinuousBuffer() - { - $aes = new AES(AES::MODE_CBC); - $aes->disablePadding(); - $aes->enableContinuousBuffer(); - $aes->setIV(pack('H*', '0457bdb4a6712986688349a29eb82535')); - $aes->setKey(pack('H*', '00d596e2c8189b2592fac358e7396ad2')); - $aes->decrypt(pack('H*', '9aa234ea7c750a8109a0f32d768b964e')); - $plaintext = $aes->decrypt(pack('H*', '0457bdb4a6712986688349a29eb82535')); - $expected = pack('H*', '6572617574689e1be8d2d8d43c594cf3'); - $this->assertSame($plaintext, $expected); - } } diff --git a/tests/Unit/Crypt/BlowfishTest.php b/tests/Unit/Crypt/BlowfishTest.php index 4d095664..f6611ea2 100644 --- a/tests/Unit/Crypt/BlowfishTest.php +++ b/tests/Unit/Crypt/BlowfishTest.php @@ -56,26 +56,22 @@ class Unit_Crypt_BlowfishTest extends PhpseclibTestCase array(pack('H*', '0123456789ABCDEF'), pack('H*', '0000000000000000'), pack('H*', '245946885754369A')), array(pack('H*', 'FEDCBA9876543210'), pack('H*', 'FFFFFFFFFFFFFFFF'), pack('H*', '6B5C5A9C5D9E0A5A')) ); - $result = array(); - - foreach ($engines as $engine => $engineName) { - foreach ($tests as $test) { - $result[] = array($engine, $engineName, $test[0], $test[1], $test[2]); - } - } - + // @codingStandardsIgnoreStart + foreach ($engines as $engine => $engineName) + foreach ($tests as $test) + $result[] = array($engine, $engineName, $test[0], $test[1], $test[2]); + // @codingStandardsIgnoreEnd return $result; } /** - * @dataProvider engineVectors - */ + * @dataProvider engineVectors + */ public function testVectors($engine, $engineName, $key, $plaintext, $expected) { - $bf = new Blowfish(Blowfish::MODE_CBC); + $bf = new Blowfish(); $bf->setKey($key); - $bf->setIV(str_repeat("\0", $bf->getBlockLength() >> 3)); if (!$bf->isValidEngine($engine)) { self::markTestSkipped('Unable to initialize ' . $engineName . ' engine'); } diff --git a/tests/Unit/Crypt/DESTest.php b/tests/Unit/Crypt/DESTest.php new file mode 100644 index 00000000..a1fbea6f --- /dev/null +++ b/tests/Unit/Crypt/DESTest.php @@ -0,0 +1,78 @@ + + * @copyright MMXIII Andreas Fischer + * @license http://www.opensource.org/licenses/mit-license.html MIT License + */ + +use phpseclib\Crypt\Base; +use phpseclib\Crypt\DES; + +// the AES tests establish the correctness of the modes of operation. this test is inteded to establish the consistency of +// key and iv padding between the multiple engines +class Unit_Crypt_DESTest extends PhpseclibTestCase +{ + public function testEncryptPadding() + { + $des = new DES(Base::MODE_CBC); + $des->setKey('d'); + $des->setIV('d'); + + $des->setPreferredEngine(Base::ENGINE_INTERNAL); + + $result = pack('H*', '3e7613642049af1e'); + + $internal = $des->encrypt('d'); + $this->assertEquals($result, $internal, 'Failed asserting that the internal engine produced the correct result'); + + $des->setPreferredEngine(Base::ENGINE_MCRYPT); + if ($des->getEngine() == Base::ENGINE_MCRYPT) { + $mcrypt = $des->encrypt('d'); + $this->assertEquals($result, $mcrypt, 'Failed asserting that the mcrypt engine produced the correct result'); + } else { + self::markTestSkipped('Unable to initialize mcrypt engine'); + } + + $des->setPreferredEngine(Base::ENGINE_OPENSSL); + if ($des->getEngine() == Base::ENGINE_OPENSSL) { + $openssl = $des->encrypt('d'); + $this->assertEquals($result, $openssl, 'Failed asserting that the OpenSSL engine produced the correct result'); + } else { + self::markTestSkipped('Unable to initialize OpenSSL engine'); + } + } + + // phpseclib null pads ciphertext's if they're not long enough and you're in ecb / cbc mode. this silent failure mode is consistent + // with mcrypt's behavior. maybe throwing an exception would be better but whatever. this test is more intended to establish consistent + // behavior between the various engine's + public function testDecryptPadding() + { + $des = new DES(Base::MODE_CBC); + $des->disablePadding(); + // when the key and iv are not specified they should be null padded + //$des->setKey(); + //$des->setIV(); + + $des->setPreferredEngine(Base::ENGINE_INTERNAL); + $internal = $des->decrypt('d'); + + $result = pack('H*', '79b305d1ce555221'); + $this->assertEquals($result, $internal, 'Failed asserting that the internal engine produced the correct result'); + + $des->setPreferredEngine(Base::ENGINE_MCRYPT); + if ($des->getEngine() == Base::ENGINE_MCRYPT) { + $mcrypt = $des->decrypt('d'); + $this->assertEquals($result, $mcrypt, 'Failed asserting that the mcrypt engine produced the correct result'); + } else { + self::markTestSkipped('Unable to initialize mcrypt engine'); + } + + $des->setPreferredEngine(Base::ENGINE_OPENSSL); + if ($des->getEngine() == Base::ENGINE_OPENSSL) { + $openssl = $des->decrypt('d'); + $this->assertEquals($result, $openssl, 'Failed asserting that the OpenSSL engine produced the correct result'); + } else { + self::markTestSkipped('Unable to initialize OpenSSL engine'); + } + } +} diff --git a/tests/Unit/Crypt/Hash/MD5Test.php b/tests/Unit/Crypt/Hash/MD5Test.php new file mode 100644 index 00000000..431184ee --- /dev/null +++ b/tests/Unit/Crypt/Hash/MD5Test.php @@ -0,0 +1,49 @@ + + * @copyright 2012 Andreas Fischer + * @license http://www.opensource.org/licenses/mit-license.html MIT License + */ + +use phpseclib\Crypt\Hash; + +class Unit_Crypt_Hash_MD5Test extends Unit_Crypt_Hash_TestCase +{ + public function getInstance() + { + return new Hash('md5'); + } + + /** + * @dataProvider hashData() + */ + public function testHash($message, $result) + { + $this->assertHashesTo($this->getInstance(), $message, $result); + } + + public static function hashData() + { + return array( + array('', 'd41d8cd98f00b204e9800998ecf8427e'), + array('The quick brown fox jumps over the lazy dog', '9e107d9d372bb6826bd81d3542a419d6'), + array('The quick brown fox jumps over the lazy dog.', 'e4d909c290d0fb1ca068ffaddf22cbd0'), + ); + } + + /** + * @dataProvider hmacData() + */ + public function testHMAC($key, $message, $result) + { + $this->assertHMACsTo($this->getInstance(), $key, $message, $result); + } + + public static function hmacData() + { + return array( + array('', '', '74e6f7298a9c2d168935f58c001bad88'), + array('key', 'The quick brown fox jumps over the lazy dog', '80070713463e7749b90c2dc24911e275'), + ); + } +} diff --git a/tests/Unit/Crypt/Hash/SHA256Test.php b/tests/Unit/Crypt/Hash/SHA256Test.php new file mode 100644 index 00000000..bad46b36 --- /dev/null +++ b/tests/Unit/Crypt/Hash/SHA256Test.php @@ -0,0 +1,81 @@ + + * @copyright 2014 Andreas Fischer + * @license http://www.opensource.org/licenses/mit-license.html MIT License + */ + +use phpseclib\Crypt\Hash; + +class Unit_Crypt_Hash_SHA256Test extends Unit_Crypt_Hash_TestCase +{ + public function getInstance() + { + return new Hash('sha256'); + } + + /** + * @dataProvider hashData() + */ + public function testHash($message, $result) + { + $this->assertHashesTo($this->getInstance(), $message, $result); + } + + public static function hashData() + { + return array( + array( + '', + 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' + ), + array( + 'The quick brown fox jumps over the lazy dog', + 'd7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592', + ), + array( + 'The quick brown fox jumps over the lazy dog.', + 'ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c', + ), + ); + } + + /** + * @dataProvider hmacData() + */ + public function testHMAC($key, $message, $result) + { + $this->assertHMACsTo($this->getInstance(), $key, $message, $result); + } + + public static function hmacData() + { + return array( + // RFC 4231 + // Test Case 1 + array( + pack('H*', '0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b'), + pack('H*', '4869205468657265'), + 'b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7', + ), + // Test Case 2 + array( + pack('H*', '4a656665'), + pack('H*', '7768617420646f2079612077616e7420666f72206e6f7468696e673f'), + '5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843', + ), + // Test Case 3 + array( + pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'), + pack('H*', 'dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'), + '773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe', + ), + // Test Case 4 + array( + pack('H*', '0102030405060708090a0b0c0d0e0f10111213141516171819'), + pack('H*', 'cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd'), + '82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b', + ), + ); + } +} diff --git a/tests/Unit/Crypt/Hash/SHA256_96Test.php b/tests/Unit/Crypt/Hash/SHA256_96Test.php new file mode 100644 index 00000000..85aaf295 --- /dev/null +++ b/tests/Unit/Crypt/Hash/SHA256_96Test.php @@ -0,0 +1,32 @@ + + * @copyright 2014 Andreas Fischer + * @license http://www.opensource.org/licenses/mit-license.html MIT License + */ + +use phpseclib\Crypt\Hash; + +class Unit_Crypt_Hash_SHA256_96Test extends Unit_Crypt_Hash_SHA256Test +{ + public function getInstance() + { + return new Hash('sha256-96'); + } + + /** + * @dataProvider hashData() + */ + public function testHash($message, $longResult) + { + parent::testHash($message, substr($longResult, 0, 24)); + } + + /** + * @dataProvider hmacData() + */ + public function testHMAC($key, $message, $longResult) + { + parent::testHMAC($key, $message, substr($longResult, 0, 24)); + } +} diff --git a/tests/Unit/Crypt/Hash/SHA512Test.php b/tests/Unit/Crypt/Hash/SHA512Test.php new file mode 100644 index 00000000..ad2e63e3 --- /dev/null +++ b/tests/Unit/Crypt/Hash/SHA512Test.php @@ -0,0 +1,81 @@ + + * @copyright 2014 Andreas Fischer + * @license http://www.opensource.org/licenses/mit-license.html MIT License + */ + +use phpseclib\Crypt\Hash; + +class Unit_Crypt_Hash_SHA512Test extends Unit_Crypt_Hash_TestCase +{ + public function getInstance() + { + return new Hash('sha512'); + } + + /** + * @dataProvider hashData() + */ + public function testHash($message, $result) + { + $this->assertHashesTo($this->getInstance(), $message, $result); + } + + public static function hashData() + { + return array( + array( + '', + 'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e' + ), + array( + 'The quick brown fox jumps over the lazy dog', + '07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6', + ), + array( + 'The quick brown fox jumps over the lazy dog.', + '91ea1245f20d46ae9a037a989f54f1f790f0a47607eeb8a14d12890cea77a1bbc6c7ed9cf205e67b7f2b8fd4c7dfd3a7a8617e45f3c463d481c7e586c39ac1ed', + ), + ); + } + + /** + * @dataProvider hmacData() + */ + public function testHMAC($key, $message, $result) + { + $this->assertHMACsTo($this->getInstance(), $key, $message, $result); + } + + public static function hmacData() + { + return array( + // RFC 4231 + // Test Case 1 + array( + pack('H*', '0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b'), + pack('H*', '4869205468657265'), + '87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854', + ), + // Test Case 2 + array( + pack('H*', '4a656665'), + pack('H*', '7768617420646f2079612077616e7420666f72206e6f7468696e673f'), + '164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737', + ), + // Test Case 3 + array( + pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'), + pack('H*', 'dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'), + 'fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb', + ), + // Test Case 4 + array( + pack('H*', '0102030405060708090a0b0c0d0e0f10111213141516171819'), + pack('H*', 'cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd'), + 'b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd', + ), + ); + } +} diff --git a/tests/Unit/Crypt/Hash/SHA512_96Test.php b/tests/Unit/Crypt/Hash/SHA512_96Test.php new file mode 100644 index 00000000..760fa243 --- /dev/null +++ b/tests/Unit/Crypt/Hash/SHA512_96Test.php @@ -0,0 +1,32 @@ + + * @copyright 2014 Andreas Fischer + * @license http://www.opensource.org/licenses/mit-license.html MIT License + */ + +use phpseclib\Crypt\Hash; + +class Unit_Crypt_Hash_SHA512_96Test extends Unit_Crypt_Hash_SHA512Test +{ + public function getInstance() + { + return new Hash('sha512-96'); + } + + /** + * @dataProvider hashData() + */ + public function testHash($message, $longResult) + { + parent::testHash($message, substr($longResult, 0, 24)); + } + + /** + * @dataProvider hmacData() + */ + public function testHMAC($key, $message, $longResult) + { + parent::testHMAC($key, $message, substr($longResult, 0, 24)); + } +} diff --git a/tests/Unit/Crypt/Hash/TestCase.php b/tests/Unit/Crypt/Hash/TestCase.php new file mode 100644 index 00000000..2ef63c6b --- /dev/null +++ b/tests/Unit/Crypt/Hash/TestCase.php @@ -0,0 +1,52 @@ + + * @copyright 2012 Andreas Fischer + * @license http://www.opensource.org/licenses/mit-license.html MIT License + */ + +use phpseclib\Crypt\Hash; + +abstract class Unit_Crypt_Hash_TestCase extends PhpseclibTestCase +{ + public static function setUpBeforeClass() + { + if (!defined('CRYPT_HASH_MODE')) { + define('CRYPT_HASH_MODE', Hash::MODE_INTERNAL); + } + } + + public function setUp() + { + if (defined('CRYPT_HASH_MODE') && CRYPT_HASH_MODE !== Hash::MODE_INTERNAL) { + $this->markTestSkipped( + 'Skipping test because CRYPT_HASH_MODE is not defined as \phpseclib\Crypt\Hash::MODE_INTERNAL.' + ); + } + } + + protected function assertHashesTo(Hash $hash, $message, $expected) + { + $this->assertEquals( + strtolower($expected), + bin2hex($hash->hash($message)), + sprintf("Failed asserting that '%s' hashes to '%s'.", $message, $expected) + ); + } + + protected function assertHMACsTo(Hash $hash, $key, $message, $expected) + { + $hash->setKey($key); + + $this->assertEquals( + strtolower($expected), + bin2hex($hash->hash($message)), + sprintf( + "Failed asserting that '%s' HMACs to '%s' with key '%s'.", + $message, + $expected, + $key + ) + ); + } +} diff --git a/tests/Unit/Crypt/HashTest.php b/tests/Unit/Crypt/HashTest.php deleted file mode 100644 index d5307d43..00000000 --- a/tests/Unit/Crypt/HashTest.php +++ /dev/null @@ -1,423 +0,0 @@ - - * @copyright 2012 Andreas Fischer - * @license http://www.opensource.org/licenses/mit-license.html MIT License - */ - -use phpseclib\Crypt\Hash; - -class Unit_Crypt_HashTest extends PhpseclibTestCase -{ - protected function assertHashesTo($hash, $message, $expected) - { - $hash = new Hash($hash); - - $this->assertSame( - strtolower($expected), - bin2hex($hash->hash($message)), - sprintf("Failed asserting that '%s' hashes to '%s'.", $message, $expected) - ); - } - - protected function assertHMACsTo($hash, $key, $message, $expected) - { - $hash = new Hash($hash); - $hash->setKey($key); - - $this->assertSame( - strtolower($expected), - bin2hex($hash->hash($message)), - sprintf( - "Failed asserting that '%s' HMACs to '%s' with key '%s'.", - $message, - $expected, - $key - ) - ); - } - - public static function hashData() - { - return array( - array('md5', '', 'd41d8cd98f00b204e9800998ecf8427e'), - array('md5', 'The quick brown fox jumps over the lazy dog', '9e107d9d372bb6826bd81d3542a419d6'), - array('md5', 'The quick brown fox jumps over the lazy dog.', 'e4d909c290d0fb1ca068ffaddf22cbd0'), - array('sha1', 'The quick brown fox jumps over the lazy dog', '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12'), - array('sha1', 'The quick brown fox jumps over the lazy dog.', '408d94384216f890ff7a0c3528e8bed1e0b01621'), - array( - 'sha256', - '', - 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' - ), - array( - 'sha256', - 'The quick brown fox jumps over the lazy dog', - 'd7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592', - ), - array( - 'sha256', - 'The quick brown fox jumps over the lazy dog.', - 'ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c', - ), - array( - 'sha384', - '', - '38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b' - ), - array( - 'sha384', - 'The quick brown fox jumps over the lazy dog', - 'ca737f1014a48f4c0b6dd43cb177b0afd9e5169367544c494011e3317dbf9a509cb1e5dc1e85a941bbee3d7f2afbc9b1', - ), - array( - 'sha512', - '', - 'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e' - ), - array( - 'sha512', - 'The quick brown fox jumps over the lazy dog', - '07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6', - ), - array( - 'sha512', - 'The quick brown fox jumps over the lazy dog.', - '91ea1245f20d46ae9a037a989f54f1f790f0a47607eeb8a14d12890cea77a1bbc6c7ed9cf205e67b7f2b8fd4c7dfd3a7a8617e45f3c463d481c7e586c39ac1ed', - ), - array( - 'whirlpool', - 'The quick brown fox jumps over the lazy dog.', - '87a7ff096082e3ffeb86db10feb91c5af36c2c71bc426fe310ce662e0338223e217def0eab0b02b80eecf875657802bc5965e48f5c0a05467756f0d3f396faba' - ), - array( - 'whirlpool', - 'The quick brown fox jumps over the lazy dog.', - '87a7ff096082e3ffeb86db10feb91c5af36c2c71bc426fe310ce662e0338223e217def0eab0b02b80eecf875657802bc5965e48f5c0a05467756f0d3f396faba' - ), - array( - 'whirlpool', - 'The quick brown fox jumps over the lazy dog.', - '87a7ff096082e3ffeb86db10feb91c5af36c2c71bc426fe310ce662e0338223e217def0eab0b02b80eecf875657802bc5965e48f5c0a05467756f0d3f396faba' - ), - // from http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA512_224.pdf - array( - 'sha512/224', - 'abc', - '4634270f707b6a54daae7530460842e20e37ed265ceee9a43e8924aa' - ), - array( - 'sha512/224', - 'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu', - '23fec5bb94d60b23308192640b0c453335d664734fe40e7268674af9' - ), - // from http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA512_256.pdf - array( - 'sha512/256', - 'abc', - '53048e2681941ef99b2e29b76b4c7dabe4c2d0c634fc6d46e0e2f13107e7af23' - ), - array( - 'sha512/256', - 'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu', - '3928e184fb8690f840da3988121d31be65cb9d3ef83ee6146feac861e19b563a' - ), - // from http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA224.pdf - array( - 'sha224', - 'abc', - '23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7E36C9DA7' - ), - array( - 'sha224', - 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq', - '75388B16512776CC5DBA5DA1FD890150B0C6455CB4F58B1952522525' - ), - ); - } - - /** - * @dataProvider hmacData() - */ - public function testHMAC($hash, $key, $message, $result) - { - $this->assertHMACsTo($hash, $key, $message, $result); - } - - /** - * @dataProvider hmacData() - */ - public function testHMAC96($hash, $key, $message, $result) - { - $this->assertHMACsTo($hash . '-96', $key, $message, substr($result, 0, 24)); - } - - public static function hmacData() - { - return array( - array('md5', '', '', '74e6f7298a9c2d168935f58c001bad88'), - array('md5', 'key', 'The quick brown fox jumps over the lazy dog', '80070713463e7749b90c2dc24911e275'), - - array( - 'whirlpool', - 'abcd', - 'The quick brown fox jumps over the lazy dog', - 'e71aabb2588d789292fa6fef00b35cc269ec3ea912b1c1cd7127daf95f004a5df5392ee563d322bac7e19d9eab161932fe9c257d63e0d09eca0d91ab4010125e', - ), - - // from https://tools.ietf.org/rfc/rfc4231.txt - // test case 1 - array( - 'sha224', - str_repeat("\x0b", 20), - 'Hi There', - '896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22', - ), - // test case 2 - array( - 'sha224', - 'Jefe', - 'what do ya want for nothing?', - 'a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44', - ), - // test case 3 - array( - 'sha224', - pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'), - pack('H*', 'dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'), - '7fb3cb3588c6c1f6ffa9694d7d6ad2649365b0c1f65d69d1ec8333ea', - ), - // test case 4 - array( - 'sha224', - pack('H*', '0102030405060708090a0b0c0d0e0f10111213141516171819'), - pack('H*', 'cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd'), - '6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a', - ), - // skip test case 5; truncation is only supported to 96 bits (eg. sha1-96) and that's already unit tested - // test case 6 - array( - 'sha224', - pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'), - 'Test Using Larger Than Block-Size Key - Hash Key First', - '95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e', - ), - // test case 7 - array( - 'sha224', - pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'), - 'This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.', - '3a854166ac5d9f023f54d517d0b39dbd946770db9c2b95c9f6f565d1' - ), - - // test case 1 - array( - 'sha256', - str_repeat("\x0b", 20), - 'Hi There', - 'b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7', - ), - // test case 2 - array( - 'sha256', - 'Jefe', - 'what do ya want for nothing?', - '5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843', - ), - // test case 3 - array( - 'sha256', - pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'), - pack('H*', 'dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'), - '773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe', - ), - // test case 4 - array( - 'sha256', - pack('H*', '0102030405060708090a0b0c0d0e0f10111213141516171819'), - pack('H*', 'cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd'), - '82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b', - ), - // skip test case 5; truncation is only supported to 96 bits (eg. sha1-96) and that's already unit tested - // test case 6 - array( - 'sha256', - pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'), - 'Test Using Larger Than Block-Size Key - Hash Key First', - '60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54', - ), - // test case 7 - array( - 'sha256', - pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'), - 'This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.', - '9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2' - ), - - // test case 1 - array( - 'sha384', - str_repeat("\x0b", 20), - 'Hi There', - 'afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59cfaea9ea9076ede7f4af152e8b2fa9cb6', - ), - // test case 2 - array( - 'sha384', - 'Jefe', - 'what do ya want for nothing?', - 'af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649', - ), - // test case 3 - array( - 'sha384', - pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'), - pack('H*', 'dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'), - '88062608d3e6ad8a0aa2ace014c8a86f0aa635d947ac9febe83ef4e55966144b2a5ab39dc13814b94e3ab6e101a34f27', - ), - // test case 4 - array( - 'sha384', - pack('H*', '0102030405060708090a0b0c0d0e0f10111213141516171819'), - pack('H*', 'cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd'), - '3e8a69b7783c25851933ab6290af6ca77a9981480850009cc5577c6e1f573b4e6801dd23c4a7d679ccf8a386c674cffb', - ), - // skip test case 5; truncation is only supported to 96 bits (eg. sha1-96) and that's already unit tested - // test case 6 - array( - 'sha384', - pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'), - 'Test Using Larger Than Block-Size Key - Hash Key First', - '4ece084485813e9088d2c63a041bc5b44f9ef1012a2b588f3cd11f05033ac4c60c2ef6ab4030fe8296248df163f44952', - ), - // test case 7 - array( - 'sha384', - pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'), - 'This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.', - '6617178e941f020d351e2f254e8fd32c602420feb0b8fb9adccebb82461e99c5a678cc31e799176d3860e6110c46523e' - ), - - // test case 1 - array( - 'sha512', - str_repeat("\x0b", 20), - 'Hi There', - '87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854', - ), - // test case 2 - array( - 'sha512', - 'Jefe', - 'what do ya want for nothing?', - '164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737', - ), - // test case 3 - array( - 'sha512', - pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'), - pack('H*', 'dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'), - 'fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb', - ), - // test case 4 - array( - 'sha512', - pack('H*', '0102030405060708090a0b0c0d0e0f10111213141516171819'), - pack('H*', 'cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd'), - 'b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd', - ), - // skip test case 5; truncation is only supported to 96 bits (eg. sha1-96) and that's already unit tested - // test case 6 - array( - 'sha512', - pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'), - 'Test Using Larger Than Block-Size Key - Hash Key First', - '80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598', - ), - // test case 7 - array( - 'sha512', - pack('H*', 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'), - 'This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.', - 'e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58' - ), - ); - } - - /** - * @dataProvider hashData() - */ - public function testHash($hash, $message, $result) - { - $this->assertHashesTo($hash, $message, $result); - } - - /** - * @dataProvider hashData() - */ - public function testHash96($hash, $message, $result) - { - $this->assertHashesTo($hash . '-96', $message, substr($result, 0, 24)); - } - - public function testConstructorDefault() - { - $hash = new Hash(); - $this->assertSame($hash->getHash(), 'sha256'); - } - - /** - * @expectedException \phpseclib\Exception\UnsupportedAlgorithmException - */ - public function testConstructorArgumentInvalid() - { - new Hash('abcdefghijklmnopqrst'); - } - - public function testConstructorArgumentValid() - { - $hash = new Hash('whirlpool'); - $this->assertSame($hash->getHash(), 'whirlpool'); - } - - /** - * @expectedException \phpseclib\Exception\UnsupportedAlgorithmException - */ - public function testSetHashInvalid() - { - $hash = new Hash('md5'); - $hash->setHash('abcdefghijklmnopqrst-96'); - } - - public function testSetHashValid() - { - $hash = new Hash('md5'); - $this->assertSame($hash->getHash(), 'md5'); - $hash->setHash('sha1'); - $this->assertSame($hash->getHash(), 'sha1'); - } - - /** - * @dataProvider lengths - */ - public function testGetLengthKnown($algorithm, $length) - { - $hash = new Hash($algorithm); - $this->assertSame($hash->getLength(), $length); - } - - public function lengths() - { - return array( - // known - array('md5-96', 12), - array('md5', 16), - array('sha1', 20), - array('sha256', 32), - array('sha384', 48), - array('sha512', 64), - // unknown - array('whirlpool', 64), - ); - } -} diff --git a/tests/Unit/Crypt/RC2Test.php b/tests/Unit/Crypt/RC2Test.php index 93dbf458..7476823b 100644 --- a/tests/Unit/Crypt/RC2Test.php +++ b/tests/Unit/Crypt/RC2Test.php @@ -30,15 +30,12 @@ class Unit_Crypt_RC2Test extends PhpseclibTestCase array('88bca90e90875a7f0f79c384627bafb2', 128, '0000000000000000', '2269552ab0f85ca6'), array('88bca90e90875a7f0f79c384627bafb216f80a6f85920584c42fceb0be255daf1e', 129, '0000000000000000', '5b78d3a43dfff1f1') ); - $result = array(); - - foreach ($this->engines as $engine => $engineName) { - foreach ($tests as $test) { - $result[] = array($engine, $engineName, $test[0], $test[1], $test[2], $test[3]); - } - } - + // @codingStandardsIgnoreStart + foreach ($this->engines as $engine => $engineName) + foreach ($tests as $test) + $result[] = array($engine, $engineName, $test[0], $test[1], $test[2], $test[3]); + // @codingStandardsIgnoreEnd return $result; } @@ -106,15 +103,14 @@ class Unit_Crypt_RC2Test extends PhpseclibTestCase } /** - * @dataProvider engineVectors - */ + * @dataProvider engineVectors + */ public function testVectors($engine, $engineName, $key, $keyLen, $plaintext, $ciphertext) { - $rc2 = new RC2(RC2::MODE_CBC); + $rc2 = new RC2(); $rc2->disablePadding(); $rc2->setKeyLength($keyLen); $rc2->setKey(pack('H*', $key)); // could also do $rc2->setKey(pack('H*', $key), $keyLen) - $rc2->setIV(str_repeat("\0", $rc2->getBlockLength() >> 3)); if (!$rc2->isValidEngine($engine)) { self::markTestSkipped('Unable to initialize ' . $engineName . ' engine'); } @@ -122,8 +118,5 @@ class Unit_Crypt_RC2Test extends PhpseclibTestCase $result = bin2hex($rc2->encrypt(pack('H*', $plaintext))); $this->assertEquals($result, $ciphertext, "Failed asserting that $plaintext yielded expected output in $engineName engine"); - - $result = bin2hex($rc2->decrypt(pack('H*', $ciphertext))); - $this->assertEquals($result, $plaintext, "Failed asserting that decrypted result yielded $plaintext as a result in $engineName engine"); } } diff --git a/tests/Unit/Crypt/RC4Test.php b/tests/Unit/Crypt/RC4Test.php index 1a020ff8..92697371 100644 --- a/tests/Unit/Crypt/RC4Test.php +++ b/tests/Unit/Crypt/RC4Test.php @@ -181,23 +181,19 @@ class Unit_Crypt_RC4Test extends PhpseclibTestCase ) ) ); - $result = array(); - - foreach ($engines as $engine => $engineName) { - foreach ($tests as $test) { - foreach ($test['output'] as $output) { - $result[] = array($engine, $engineName, $test['key'], $output['offset'], $output['result']); - } - } - } - + // @codingStandardsIgnoreStart + foreach ($engines as $engine => $engineName) + foreach ($tests as $test) + foreach ($test['output'] as $output) + $result[] = array($engine, $engineName, $test['key'], $output['offset'], $output['result']); + // @codingStandardsIgnoreEnd return $result; } /** - * @dataProvider engineVectors - */ + * @dataProvider engineVectors + */ public function testVectors($engine, $engineName, $key, $offset, $expected) { $rc4 = new RC4(); diff --git a/tests/Unit/Crypt/RSA/CreateKeyTest.php b/tests/Unit/Crypt/RSA/CreateKeyTest.php deleted file mode 100644 index e7478be3..00000000 --- a/tests/Unit/Crypt/RSA/CreateKeyTest.php +++ /dev/null @@ -1,34 +0,0 @@ - - * @copyright 2015 Jim Wigginton - * @license http://www.opensource.org/licenses/mit-license.html MIT License - */ - -use phpseclib\Crypt\RSA; - -class Unit_Crypt_RSA_CreateKeyTest extends PhpseclibTestCase -{ - public function testCreateKey() - { - extract(RSA::createKey(768)); - $this->assertInstanceOf('\phpseclib\Crypt\RSA', $privatekey); - $this->assertInstanceOf('\phpseclib\Crypt\RSA', $publickey); - $this->assertNotEmpty("$privatekey"); - $this->assertNotEmpty("$publickey"); - - return array($publickey, $privatekey); - } - - /** - * @depends testCreateKey - */ - public function testEncryptDecrypt($args) - { - list($publickey, $privatekey) = $args; - $ciphertext = $publickey->encrypt('zzz'); - $this->assertInternalType('string', $ciphertext); - $plaintext = $privatekey->decrypt($ciphertext); - $this->assertSame($plaintext, 'zzz'); - } -} diff --git a/tests/Unit/Crypt/RSA/LoadKeyTest.php b/tests/Unit/Crypt/RSA/LoadKeyTest.php index 5f84e698..a80b8d2f 100644 --- a/tests/Unit/Crypt/RSA/LoadKeyTest.php +++ b/tests/Unit/Crypt/RSA/LoadKeyTest.php @@ -6,9 +6,6 @@ */ use phpseclib\Crypt\RSA; -use phpseclib\Crypt\RSA\PKCS1; -use phpseclib\Crypt\RSA\PuTTY; -use phpseclib\Math\BigInteger; class Unit_Crypt_RSA_LoadKeyTest extends PhpseclibTestCase { @@ -18,7 +15,7 @@ class Unit_Crypt_RSA_LoadKeyTest extends PhpseclibTestCase $key = 'zzzzzzzzzzzzzz'; - $this->assertFalse($rsa->load($key)); + $this->assertFalse($rsa->loadKey($key)); } public function testPKCS1Key() @@ -39,7 +36,7 @@ U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ 37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0= -----END RSA PRIVATE KEY-----'; - $this->assertTrue($rsa->load($key)); + $this->assertTrue($rsa->loadKey($key)); $this->assertInternalType('string', $rsa->getPrivateKey()); } @@ -62,7 +59,7 @@ U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ -----END RSA PRIVATE KEY-----'; $key = str_replace(array("\r", "\n", "\r\n"), ' ', $key); - $this->assertTrue($rsa->load($key)); + $this->assertTrue($rsa->loadKey($key)); $this->assertInternalType('string', $rsa->getPrivateKey()); } @@ -82,7 +79,7 @@ X6zk7S0ljKtt2jny2+00VsBerQJBAJGC1Mg5Oydo5NwD6BiROrPxGo2bpTbu/fhrT8ebHkTz2epl U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ 37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0='; - $this->assertTrue($rsa->load($key)); + $this->assertTrue($rsa->loadKey($key)); $this->assertInternalType('string', $rsa->getPrivateKey()); } @@ -102,7 +99,7 @@ U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ 'U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ' . '37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0='; - $this->assertTrue($rsa->load($key)); + $this->assertTrue($rsa->loadKey($key)); $this->assertInternalType('string', $rsa->getPrivateKey()); } @@ -123,7 +120,7 @@ U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ '37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0='; $key = base64_decode($key); - $this->assertTrue($rsa->load($key)); + $this->assertTrue($rsa->loadKey($key)); $this->assertInternalType('string', $rsa->getPrivateKey()); } @@ -162,7 +159,7 @@ GF/qoZyC1mbqdtyyeWgHtVbJVUORmpbNnXOII9duEqBUNDiO9VSZNn/8h/VsYeAB xryZaRDVmtMuf/OZBQ== -----END ENCRYPTED PRIVATE KEY-----'; - $this->assertTrue($rsa->load($key)); + $this->assertTrue($rsa->loadKey($key)); $this->assertInternalType('string', $rsa->getPrivateKey()); } @@ -185,12 +182,12 @@ U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ -----END RSA PRIVATE KEY-----'; $rsa->setPassword('password'); - $this->assertTrue($rsa->load($key)); + $this->assertTrue($rsa->loadKey($key)); - $key = $rsa->getPrivateKey('PKCS8'); + $key = $rsa->getPrivateKey(RSA::PRIVATE_FORMAT_PKCS8); $this->assertInternalType('string', $key); - $this->assertTrue($rsa->load($key)); + $this->assertTrue($rsa->loadKey($key)); } public function testPubKey1() @@ -206,7 +203,7 @@ gPiUWOPatVkt7+Bs3h5Ramxh7XjBOXeulmCpGSynXNcpZ/06+vofGi/2MlpQZNhH Ao8eayMp6FcvNucIpUndo1X8dKMv3Y26ZQIDAQAB -----END RSA PUBLIC KEY-----'; - $this->assertTrue($rsa->load($key)); + $this->assertTrue($rsa->loadKey($key)); $this->assertInternalType('string', $rsa->getPublicKey()); $this->assertFalse($rsa->getPrivateKey()); } @@ -225,7 +222,7 @@ lmCpGSynXNcpZ/06+vofGi/2MlpQZNhHAo8eayMp6FcvNucIpUndo1X8dKMv3Y26 ZQIDAQAB -----END PUBLIC KEY-----'; - $this->assertTrue($rsa->load($key)); + $this->assertTrue($rsa->loadKey($key)); $this->assertInternalType('string', $rsa->getPublicKey()); $this->assertFalse($rsa->getPrivateKey()); } @@ -239,7 +236,7 @@ ZQIDAQAB 'GkVb1/3j+skZ6UtW+5u09lHNsj6tQ51s1SPrCBkedbNf0Tp0GbMJDyR4e9T04ZZw== ' . 'phpseclib-generated-key'; - $this->assertTrue($rsa->load($key)); + $this->assertTrue($rsa->loadKey($key)); $this->assertInternalType('string', $rsa->getPublicKey()); $this->assertFalse($rsa->getPrivateKey()); } @@ -255,7 +252,7 @@ ZQIDAQAB 'b6wYtY/q/WtUFr3nK+x0lgOtokhnJfRR/6fnmC1CztPnIT4BWK81VGKWONAxuhMyQ5XChyu6S9'. 'mWG5tUlUI/5'; - $this->assertTrue($rsa->load($key)); + $this->assertTrue($rsa->loadKey($key)); $this->assertSame($rsa->getPublicKeyFingerprint('md5'), 'bd:2c:2f:31:b9:ef:b8:f8:ad:fc:40:a6:94:4f:28:82'); $this->assertSame($rsa->getPublicKeyFingerprint('sha256'), 'N9sV2uSNZEe8TITODku0pRI27l+Zk0IY0TrRTw3ozwM'); } @@ -273,7 +270,7 @@ gPiUWOPatVkt7+Bs3h5Ramxh7XjBOXeulmCpGSynXNcpZ/06+vofGi/2MlpQZNhH Ao8eayMp6FcvNucIpUndo1X8dKMv3Y26ZQIDAQAB -----END RSA PUBLIC KEY-----'; - $this->assertTrue($rsa->load($key)); + $this->assertTrue($rsa->loadKey($key)); $this->assertTrue($rsa->setPrivateKey()); $this->assertGreaterThanOrEqual(1, strlen("$rsa")); $this->assertFalse($rsa->getPublicKey()); @@ -293,11 +290,11 @@ Ao8eayMp6FcvNucIpUndo1X8dKMv3Y26ZQIDAQAB AQAB '; - $rsa->load($key); + $rsa->loadKey($key); $rsa->setPublicKey(); - $newkey = $rsa->getPublicKey('XML'); + $newkey = $rsa->getPublicKey(RSA::PUBLIC_FORMAT_XML); - $this->assertSame(strtolower(preg_replace('#\s#', '', $key)), strtolower(preg_replace('#\s#', '', $newkey))); + $this->assertSame(preg_replace('#\s#', '', $key), preg_replace('#\s#', '', $newkey)); } /** @@ -314,224 +311,10 @@ JWrQdxx/WNN+ABG426rgYYbeGcIlWLZCw6Bx/1HtN5ef6nVEoiGNChYKIRB4QFOi 01smFxps1w8ZIQnD6wIDAQAB -----END PUBLIC KEY-----'; - $rsa->load($key); + $rsa->loadKey($key); $rsa->setPublicKey(); $newkey = $rsa->getPublicKey(); $this->assertSame(preg_replace('#\s#', '', $key), preg_replace('#\s#', '', $newkey)); } - - /** - * @group github861 - */ - public function testPKCS8Only() - { - $rsa = new RSA(); - - $key = '-----BEGIN PRIVATE KEY----- -MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKB0yPMAbUHKqJxP -5sjG9AOrQSAYNDc34NsnZ1tsi7fZ9lHlBaKZ6gjm2U9q+/qCKv2BuGINxWo2CMJp -DHNY0QTt7hThr3B4U62z1CWWGnfLhFtHKH6jNYYOGc4x0jgT88uSrKFvUOLhjkjW -bURmJMpN+OjLJuZQZ7uwoqtT3IEDAgMBAAECgYBaElS/fEzYst/Fp2DA8lYGPTs4 -vf2JxbdWrp7phlxEH3mTbUGljkr/Jj90wnSiojFpz0jm2h4oyh5Oq9OOaJwkCYcu -2lcHJvFlhR2XEJpd1bHHcvDwZHdUjSpnO8kvwQtjuTnho2ntRzAA4wIJVSd7Tynj -0IFEKmzhSKIvIIeN8QJBANLa10R1vs+YqpLdpAuc6Z9GYhHuh1TysBPw2xNtw3Xf -tGPx4/53eQ0RwiHdw9Opgt8CBHErD6KzziflfxUrIXkCQQDCz4t01qYWT43kxS6k -TcnZb/obho6akGc8C1hSxFIIGUa9hAhMpY2W6GXeGpv5TZtEJZIJE1VHTLvcLSGm -ILNbAkEAgq9mWqULxYket3Yt1ZDEb5Zk9C49rJXaMhHHBoyyZ51mJcfngnE0Erid -9PWJCOf4GBYdALMqtrHwpWOlV05rKQJAd6Tz50w1MRqm8MvRe4Ny5qIJH4Kibncl -kBD/q8V7BBJSCe7fEgPTU81jUudQx+pL46yXZg+DnoiYD/9/3QHUZQJBAMBiKiZ7 -qMnD/pkHR/NFcYSYShUJS0cHyryVl7/eCclsQlZTRdnVTtKF9xPGTQC8fK0G7BDN -Z2sKniRCcDT1ZP4= ------END PRIVATE KEY-----'; - - $result = $rsa->load($key, 'PKCS8'); - - $this->assertTrue($result); - } - - public function testPKCS1EncryptionChange() - { - $rsa = new RSA(); - - $key = 'PuTTY-User-Key-File-2: ssh-rsa -Encryption: none -Comment: phpseclib-generated-key -Public-Lines: 4 -AAAAB3NzaC1yc2EAAAADAQABAAAAgQCqGKukO1De7zhZj6+H0qtjTkVxwTCpvKe4 -eCZ0FPqri0cb2JZfXJ/DgYSF6vUpwmJG8wVQZKjeGcjDOL5UlsuusFncCzWBQ7RK -NUSesmQRMSGkVb1/3j+skZ6UtW+5u09lHNsj6tQ51s1SPrCBkedbNf0Tp0GbMJDy -R4e9T04ZZw== -Private-Lines: 8 -AAAAgBYo5KOevqhsjfDNEVcmkQF8/vsU6hwS4d7ceFYDLa0PlhIAo4aE8KNtyjAQ -LiRkmJ0ZqAWTN5TH0ynryJAInTxMb2AnZuXWKt106C5JC7+S9qSCFThTAxvihEpw -BVe5dnPnJ80TFtPm+n/JkdQic2bsVSy+kNNn7y4uef5m0mMRAAAAQQDeAw6fiIQX -GukBI4eMZZt4nscy2o12KyYner3VpoeE+Np2q+Z3pvAMd/aNzQ/W9WaI+NRfcxUJ -rmfPwIGm63ilAAAAQQDEIvkdBvZtCvgHKitwxab+EQ/YxnNE5XvfIXjWE+xEL2br -oquF470c9Mm6jf/2zmn6yobE6UUvQ0O3hKSiyOAbAAAAQBGoiuSoSjafUhV7i1cE -Gpb88h5NBYZzWXGZ37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ -4p0= -Private-MAC: 03e2cb74e1d67652fbad063d2ed0478f31bdf256 -'; - $key = preg_replace('#(?assertTrue($rsa->load($key)); - - PKCS1::setEncryptionAlgorithm('AES-256-CBC'); - $rsa->setPassword('demo'); - - $encryptedKey = (string) $rsa; - - $this->assertRegExp('#AES-256-CBC#', $encryptedKey); - - $rsa = new RSA(); - $rsa->setPassword('demo'); - $this->assertTrue($rsa->load($encryptedKey)); - $rsa->setPassword(); - $rsa->setPrivateKeyFormat('PuTTY'); - $key2 = (string) $rsa; - - $this->assertSame($key, $key2); - } - - public function testRawKey() - { - $rsa = new RSA(); - - $key = array( - 'e' => new BigInteger('10001', 16), - 'n' => new BigInteger('aa18aba43b50deef38598faf87d2ab634e4571c130a9bca7b878267414faab8b471bd8965f5c9fc3' . - '818485eaf529c26246f3055064a8de19c8c338be5496cbaeb059dc0b358143b44a35449eb2641131' . - '21a455bd7fde3fac919e94b56fb9bb4f651cdb23ead439d6cd523eb08191e75b35fd13a7419b3090' . - 'f24787bd4f4e1967', 16) - ); - $this->assertTrue($rsa->load($key)); - $rsa->setPublicKeyFormat('raw'); - $this->assertEmpty("$rsa"); - } - - public function testRawComment() - { - $key = 'PuTTY-User-Key-File-2: ssh-rsa -Encryption: aes256-cbc -Comment: phpseclib-generated-key -Public-Lines: 4 -AAAAB3NzaC1yc2EAAAADAQABAAAAgQCqGKukO1De7zhZj6+H0qtjTkVxwTCpvKe4 -eCZ0FPqri0cb2JZfXJ/DgYSF6vUpwmJG8wVQZKjeGcjDOL5UlsuusFncCzWBQ7RK -NUSesmQRMSGkVb1/3j+skZ6UtW+5u09lHNsj6tQ51s1SPrCBkedbNf0Tp0GbMJDy -R4e9T04ZZw== -Private-Lines: 8 -llx04QMegql0/nE5RvcJSrGrodxt6ytuv/JX2caeZBUyQwQc2WBNYagLHyHPM9jI -9OUWz59FLhjFXZMDNMoUXxVmjwQpOAaVPYNxxFM9AF6/NXFji64K7huD9n4A+kLn -sHwMLWPR5a/tZA0r05DZNz9ULA3mQu7Hz4EQ8ifu3uTPJuTmL51x6RmudYKysb20 -fM8VzC3ukvzzRh0pujUVTr/yQdmciASVFnZlt4xQy+ZEOVUAOfwjd//AFfXTvk6x -7A45rNlU/uicHwLgoY1APvRHCFxw7F+uVW5L4mSX7NNzqBKkZ+1qpQTAfQvIfEIb -444+CXsgIyOpqt6VxJH2u6elAtE1wau3YaFR8Alm8m97rFYzRi3oDP5NZYkTCWSV -EOpSeghXSs7IilJu8I6/sB1w5dakdeBSFkIynrlFXkO0uUw+QJJWjxY8SypzgIuP -DzduF6XsQrCyo6dnIpGQCQ== -Private-MAC: 35134b7434bf828b21404099861d455e660e8740'; - $raw = PuTTY::load($key, 'password'); - $this->assertArrayHasKey('comment', $raw); - $this->assertEquals($raw['comment'], 'phpseclib-generated-key'); - - $rsa = new RSA(); - $rsa->load($raw); - $this->assertGreaterThanOrEqual(1, strlen("$rsa")); - } - - public function testPrivateMSBlob() - { - $key = 'BwIAAACkAABSU0EyAAQAAAEAAQAnh6FFs6kYe/gmb9dzqsQKmtjFE9mxNAe9mEU3OwOEEfyI' . - 'wkAx0/8dwh12fuP4wzNbdZAq4mmqCE6Lo8wTNNIJVNYEhKq5chHg1+hPDgfETFgtEO54JZSg' . - '3cBZWEV/Tq3LHEX8CaLvHZxMEfFXbTfliFYMLoJ+YK1mpg9GYcmbrVmMAKSoOgETkkiJJzYm' . - 'XftO3KOveBtvkAzjHxxSS1yP/Ba10BzeIleH96SbTuQtQRLXwRykdX9uazK+YsiSud9/PyLb' . - 'gy5TI+o28OHq5P+0y5+a9IaAQ/92UwlrkHUYfhN/xTVlUIxKlTEdUQTIf+iHif8d4ABb3OdY' . - 'JXZOW6fGeUP10jMyvbnrEoPDsYy9qfNk++0/8UP2NeO1IATszuZYg1nEXOW/5jmUxMCdiFyd' . - 'p9ES211kpEZ4XcvjGaDlaQ+bLWj05i2m/9aHYcBrfcxxvlMa/9ZvrX4DfPWeydUDDDQ4+ntp' . - 'T50BunSvmyf7cUk76Bf2sPgLXUQFoufEQ5g1Qo/v1uyhWBJzh6OSUO/DDXN/s8ec/tN05RQQ' . - 'FZQ0na+v0hOCrV9IuRqtBuj4WAj1I/A1JjwyyP9Y/6yWFPM6EcS/6lyPy30lJPoULh7G29zk' . - 'n7NVdTEkDtthdDjtX7Qhgd9qWvm5ADlmnvsS9A5m7ToOgQyOxtJoSlLitLbf/09LRycl/cdI' . - 'zoMOCEdPe3DQcyEKqUPsghAq+DKw3uZpXwHzwTdfqlHSWAnHDggFKV1HZuWc1c4rV4k4b513TqE='; - - $plaintext = 'zzz'; - - $privKey = new RSA(); - $privKey->load($key); - - $this->assertSame($privKey->getLoadedFormat(), 'MSBLOB'); - - $this->assertGreaterThanOrEqual(1, strlen("$privKey")); - - $pubKey = new RSA(); - $pubKey->load($privKey->getPublicKey('msblob')); - - $this->assertGreaterThanOrEqual(1, strlen("$pubKey")); - - $ciphertext = $pubKey->encrypt($plaintext); - - $this->assertSame($privKey->decrypt($ciphertext), $plaintext); - } - - public function testNakedOpenSSHKey() - { - $key = 'AAAAB3NzaC1yc2EAAAABIwAAAIEA/NcGSQFZ0ZgN1EbDusV6LLwLnQjs05ljKcVVP7Z6aKIJUyhUDHE30uJa5XfwPPBsZ3L3Q7S0yycVcuuHjdauugmpn9xx+gyoYs7UiV5G5rvxNcA/Tc+MofGhAMiTmNicorNAs5mv6fRoVbkpIONRXPz6WK0kjx/X04EV42Vm9Qk='; - - $rsa = new RSA(); - $rsa->load($key); - - $this->assertSame($rsa->getLoadedFormat(), 'OpenSSH'); - - $this->assertGreaterThanOrEqual(1, strlen("$rsa")); - } - - public function testPuttyPublicKey() - { - $key = '---- BEGIN SSH2 PUBLIC KEY ---- -Comment: "rsa-key-20151023" -AAAAB3NzaC1yc2EAAAABJQAAAIEAhC/CSqJ+8vgeQ4H7fJru29h/McqAC9zdGzw0 -9QsifLQ7s5MvXCavhjUPYIfV0KsdLQydNPLJcbKpXmpVD9azo61zLXwsYr8d1eHr -C/EwUYl8b0fAwEsEF3myb+ryzgA9ihY08Zs9NZdmt1Maa+I7lQcLX9F/65YdcAch -ILaEujU= ----- END SSH2 PUBLIC KEY ----'; - - $rsa = new RSA(); - $rsa->load($key); - - $this->assertSame($rsa->getLoadedFormat(), 'PuTTY'); - - $this->assertGreaterThanOrEqual(1, strlen("$rsa")); - } - - /** - * @group github960 - */ - public function testSetLoad() - { - $key = 'PuTTY-User-Key-File-2: ssh-rsa -Encryption: aes256-cbc -Comment: phpseclib-generated-key -Public-Lines: 4 -AAAAB3NzaC1yc2EAAAADAQABAAAAgQCqGKukO1De7zhZj6+H0qtjTkVxwTCpvKe4 -eCZ0FPqri0cb2JZfXJ/DgYSF6vUpwmJG8wVQZKjeGcjDOL5UlsuusFncCzWBQ7RK -NUSesmQRMSGkVb1/3j+skZ6UtW+5u09lHNsj6tQ51s1SPrCBkedbNf0Tp0GbMJDy -R4e9T04ZZw== -Private-Lines: 8 -llx04QMegql0/nE5RvcJSrGrodxt6ytuv/JX2caeZBUyQwQc2WBNYagLHyHPM9jI -9OUWz59FLhjFXZMDNMoUXxVmjwQpOAaVPYNxxFM9AF6/NXFji64K7huD9n4A+kLn -sHwMLWPR5a/tZA0r05DZNz9ULA3mQu7Hz4EQ8ifu3uTPJuTmL51x6RmudYKysb20 -fM8VzC3ukvzzRh0pujUVTr/yQdmciASVFnZlt4xQy+ZEOVUAOfwjd//AFfXTvk6x -7A45rNlU/uicHwLgoY1APvRHCFxw7F+uVW5L4mSX7NNzqBKkZ+1qpQTAfQvIfEIb -444+CXsgIyOpqt6VxJH2u6elAtE1wau3YaFR8Alm8m97rFYzRi3oDP5NZYkTCWSV -EOpSeghXSs7IilJu8I6/sB1w5dakdeBSFkIynrlFXkO0uUw+QJJWjxY8SypzgIuP -DzduF6XsQrCyo6dnIpGQCQ== -Private-MAC: 35134b7434bf828b21404099861d455e660e8740'; - - $rsa = new RSA(); - $rsa->setPrivateKey($key); - $rsa->load($key); - - $rsa = new RSA(); - $rsa->load($key); - $rsa->setPrivateKey(); - $rsa->load($rsa); - } } diff --git a/tests/Unit/Crypt/RSA/ModeTest.php b/tests/Unit/Crypt/RSA/ModeTest.php index 0dde29c7..0b90210e 100644 --- a/tests/Unit/Crypt/RSA/ModeTest.php +++ b/tests/Unit/Crypt/RSA/ModeTest.php @@ -6,7 +6,6 @@ */ use phpseclib\Crypt\RSA; -use phpseclib\Math\BigInteger; class Unit_Crypt_RSA_ModeTest extends PhpseclibTestCase { @@ -29,74 +28,19 @@ X6zk7S0ljKtt2jny2+00VsBerQJBAJGC1Mg5Oydo5NwD6BiROrPxGo2bpTbu/fhrT8ebHkTz2epl U9VQQSQzY1oZMVX8i1m5WUTLPz2yLJIBQVdXqhMCQBGoiuSoSjafUhV7i1cEGpb88h5NBYZzWXGZ 37sJ5QsW+sJyoNde3xH8vdXhzU7eT82D6X/scw9RZz+/6rCJ4p0= -----END RSA PRIVATE KEY-----'; - $rsa->load($privatekey); - $rsa->load($rsa->getPublicKey()); + $rsa->loadKey($privatekey); + $rsa->loadKey($rsa->getPublicKey()); + $rsa->setEncryptionMode(RSA::ENCRYPTION_NONE); $expected = '105b92f59a87a8ad4da52c128b8c99491790ef5a54770119e0819060032fb9e772ed6772828329567f3d7e9472154c1530f8156ba7fd732f52ca1c06' . '5a3f5ed8a96c442e4662e0464c97f133aed31262170201993085a589565d67cc9e727e0d087e3b225c8965203b271e38a499c92fc0d6502297eca712' . '4d04bd467f6f1e7c'; $expected = pack('H*', $expected); - $result = $rsa->encrypt($plaintext, RSA::PADDING_NONE); + $result = $rsa->encrypt($plaintext); $this->assertEquals($result, $expected); - $rsa->load($privatekey); - $this->assertEquals(trim($rsa->decrypt($result, RSA::PADDING_NONE), "\0"), $plaintext); - } - - /** - * @group github768 - */ - public function testPSSSigs() - { - $rsa = new RSA(); - $rsa->setHash('sha1'); - $rsa->setMGFHash('sha1'); - $rsa->load('-----BEGIN PUBLIC KEY----- -MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqGKukO1De7zhZj6+H0qtjTkVx -wTCpvKe4eCZ0FPqri0cb2JZfXJ/DgYSF6vUpwmJG8wVQZKjeGcjDOL5UlsuusFnc -CzWBQ7RKNUSesmQRMSGkVb1/3j+skZ6UtW+5u09lHNsj6tQ51s1SPrCBkedbNf0T -p0GbMJDyR4e9T04ZZwIDAQAB ------END PUBLIC KEY-----'); - - $sig = pack('H*', '1bd29a1d704a906cd7f726370ce1c63d8fb7b9a620871a05f3141a311c0d6e75fefb5d36dfb50d3ea2d37cd67992471419bfadd35da6e13b494' . - '058ddc9b568d4cfea13ddc3c62b86a6256f5f296980d1131d3eaec6089069a3de79983f73eae20198a18721338b4a66e9cfe80e4f8e4fcef7a5bead5cbb' . - 'b8ac4c76adffbc178c'); - - $this->assertTrue($rsa->verify('zzzz', $sig)); - } - - /** - * @expectedException \OutOfBoundsException - */ - public function testSmallModulo() - { - $plaintext = 'x'; - $n = new BigInteger(base64_decode('272435F22706FA96DE26E980D22DFF67'), 256); - $e = new BigInteger(base64_decode('158753FF2AF4D1E5BBAB574D5AE6B54D'), 256); - - $rsa = new RSA(); - $rsa->load(array('n' => $n, 'e' => $e)); - $rsa->encrypt($plaintext); - } - - public function testPKCS1LooseVerify() - { - $rsa = new RSA(); - $rsa->load('-----BEGIN RSA PUBLIC KEY----- -MIGJAoGBAMuqkz8ij+ESAaNvgocVGmapjlrIldmhRo4h2NX4e6IXiCLTSxASQtY4 -iqRnmyxqQSfaan2okTfQ6sP95bl8Qz8lgneW3ClC6RXG/wpJgsx7TXQ2kodlcKBF -m4k72G75QXhZ+I40ZG7cjBf1/9egakR0a0X0MpeOrKCzMBLv9+mpAgMBAAE= ------END RSA PUBLIC KEY-----'); - - $message = base64_decode('MYIBLjAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0xNDA1MTUxNDM4MzRaMC8GCSqGSIb3DQEJBDEiBCBLzLIBGdOf0L2WRrIY' . - '9KTwiHnReBW48S9C7LNRaPp5mDCBwgYLKoZIhvcNAQkQAi8xgbIwga8wgawwgakEIJDB9ZGwihf+TaiwrHQNkNHkqbN8Nuws0e77QNObkvFZMIGEMHCkbjBs' . - 'MQswCQYDVQQGEwJJVDEYMBYGA1UECgwPQXJ1YmFQRUMgUy5wLkEuMSEwHwYDVQQLDBhDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eUMxIDAeBgNVBAMMF0FydWJh' . - 'UEVDIFMucC5BLiBORyBDQSAzAhAv4L3QcFssQNLDYN/Vu40R'); - - $sig = base64_decode('XDSZWw6IcUj8ICxRJf04HzF8stzoiFAZSR2a0Rw3ziZxTOT0/NVUYJO5+9TaaREXEgxuCLpgmA+6W2SWrrGoxbbNfaI90ZoKeOAws4IX+9RfiWuooibjKcvt' . - 'GJYVVOCcjvQYxUUNbQ4EjCUonk3h7ECXfCCmWqbeq2LsyXeeYGE='); - - $this->assertTrue($rsa->verify($message, $sig, RSA::PADDING_RELAXED_PKCS1)); + $rsa->loadKey($privatekey); + $this->assertEquals(trim($rsa->decrypt($result), "\0"), $plaintext); } } diff --git a/tests/Unit/Crypt/TripleDESTest.php b/tests/Unit/Crypt/TripleDESTest.php index 2ed8f321..cd10dbe0 100644 --- a/tests/Unit/Crypt/TripleDESTest.php +++ b/tests/Unit/Crypt/TripleDESTest.php @@ -87,30 +87,26 @@ class Unit_Crypt_TripleDESTest extends PhpseclibTestCase array(str_repeat("\x01", 24), pack('H*', '0000000000000002'), pack('H*', '06E7EA22CE92708F')), array(str_repeat("\x01", 24), pack('H*', '0000000000000001'), pack('H*', '166B40B44ABA4BD6')) ); - $result = array(); - - foreach ($this->engines as $engine => $engineName) { - foreach ($tests as $test) { - $result[] = array($engine, $engineName, $test[0], $test[1], $test[2]); - } - } - + // @codingStandardsIgnoreStart + foreach ($this->engines as $engine => $engineName) + foreach ($tests as $test) + $result[] = array($engine, $engineName, $test[0], $test[1], $test[2]); + // @codingStandardsIgnoreEnd return $result; } /** - * @dataProvider engineVectors - */ + * @dataProvider engineVectors + */ public function testVectors($engine, $engineName, $key, $plaintext, $expected) { - $des = new TripleDES(TripleDES::MODE_CBC); + $des = new TripleDES(); if (!$des->isValidEngine($engine)) { self::markTestSkipped('Unable to initialize ' . $engineName . ' engine'); } $des->setPreferredEngine($engine); $des->setKey($key); - $des->setIV(str_repeat("\0", $des->getBlockLength() >> 3)); $des->disablePadding(); $result = $des->encrypt($plaintext); $plaintext = bin2hex($plaintext); @@ -139,24 +135,21 @@ class Unit_Crypt_TripleDESTest extends PhpseclibTestCase pack('H*', '84401f78fe6c10876d8ea23094ea5309'), pack('H*', '7b1f7c7e3b1c948ebd04a75ffba7d2f5')) ); - $result = array(); - - foreach ($engines as $engine => $engineName) { - foreach ($tests as $test) { - $result[] = array($engine, $engineName, $test[0], $test[1], $test[2], $test[3]); - } - } - + // @codingStandardsIgnoreStart + foreach ($engines as $engine => $engineName) + foreach ($tests as $test) + $result[] = array($engine, $engineName, $test[0], $test[1], $test[2], $test[3]); + // @codingStandardsIgnoreEnd return $result; } /** - * @dataProvider engineIVVectors - */ + * @dataProvider engineIVVectors + */ public function testVectorsWithIV($engine, $engineName, $key, $iv, $plaintext, $expected) { - $des = new TripleDES(TripleDES::MODE_CBC); + $des = new TripleDES(); if (!$des->isValidEngine($engine)) { self::markTestSkipped('Unable to initialize ' . $engineName . ' engine'); } @@ -177,7 +170,6 @@ class Unit_Crypt_TripleDESTest extends PhpseclibTestCase $des = new TripleDES(TripleDES::MODE_3CBC); $des->setKey('abcdefghijklmnopqrstuvwx'); - $des->setIV(str_repeat("\0", $des->getBlockLength() >> 3)); foreach ($this->engines as $engine => $engineName) { $des->setPreferredEngine($engine); diff --git a/tests/Unit/Crypt/TwofishTest.php b/tests/Unit/Crypt/TwofishTest.php index d678c9e1..f47443e9 100644 --- a/tests/Unit/Crypt/TwofishTest.php +++ b/tests/Unit/Crypt/TwofishTest.php @@ -19,8 +19,7 @@ class Unit_Crypt_TwofishTest extends PhpseclibTestCase ); foreach ($engines as $engine => $name) { - $tf = new Twofish(Twofish::MODE_CBC); - $tf->setIV(str_repeat("\0", $tf->getBlockLength() >> 3)); + $tf = new Twofish(); $tf->disablePadding(); // tests from https://www.schneier.com/code/ecb_ival.txt diff --git a/tests/Unit/File/ASN1Test.php b/tests/Unit/File/ASN1Test.php index c9a1ea29..035adc9c 100644 --- a/tests/Unit/File/ASN1Test.php +++ b/tests/Unit/File/ASN1Test.php @@ -18,7 +18,7 @@ class Unit_File_ASN1Test extends PhpseclibTestCase $KDC_REP = array( 'type' => ASN1::TYPE_SEQUENCE, 'children' => array( - 'pvno' => array( + 'pvno' => array( 'constant' => 0, 'optional' => true, 'explicit' => true, diff --git a/tests/Unit/File/X509/CSRTest.php b/tests/Unit/File/X509/CSRTest.php index 6e4b827d..7a91262b 100644 --- a/tests/Unit/File/X509/CSRTest.php +++ b/tests/Unit/File/X509/CSRTest.php @@ -68,29 +68,4 @@ draiRBZruwMPwPIP $this->assertInternalType('array', $csr); } - - public function testCSRDER() - { - $csr = 'MIICdzCCAV8CAQEwDDEKMAgGA1UEAwwBeDCCASIwDQYJKoZIhvcNAQEBBQADggEP' . - 'ADCCAQoCggEBALtcrFDD2AHe3x2bR00wPDsPH6FJLxr5uc1ybb+ldDB5xNVImC8P' . - 'LU6VXDZ5z68KjSovs1q0OWJWfCjlAuGLzqO35s86LI1CFuTFdkScVHMwh8zUVFoP' . - 'pG7/9rKaNxCgaHs4evxjxQP2+Ny7tBqPLb/KV0exm6Twocf963jC/Tyn57G5erRf' . - 'zpFrfK7DozhxY7znumJ4FuSn0TVkD6PPwZFn9VoTjv2ZoJmacGK+0r5yNKG799F5' . - 'K8EgDrOCfbzCZjX6GJctyn2SNPTeBuXS9piH21FGnJAryv80zG+zUqFdEyoLUGJt' . - '4Vy6+tDP9cW68fiwTZS1Oc1VeFdL1G/CrjkCAwEAAaAmMCQGCSqGSIb3DQEJDjEX' . - 'MBUwEwYKKwYBBAGCqlsBCQQFMAOCAQEwDQYJKoZIhvcNAQELBQADggEBAF4XOd+1' . - 'jkJOYRInNpHfhzSD/ktDY50gpLPuDvl4f/ZBlKrb1eDYQG5F3bnYzoZWHN4n+6Zs' . - 'CkljXs5ZPUZ5LuVpASumoG/aHXGz8c8NC3asJ1V73ljEPAfIXwqoIUoaP9jLL+Ee' . - 'zy/ZCi2NKWVo2D7ocnn79oblAem9ksSeQl4z3Gvhuug6MsMqn96NU/ZY/vjYzAjb' . - 'MAvJIVRY0rbCxbFa0K+XNJtF7GLyBxyPNFWCvADhvm9C4uPmoypYg7MY6EewJInN' . - 'xzMH7I4xDLjNu0VBa6lAxTvflp0joQHKlTYX0SDIKPbQivjZMuObPuxDtkVZ0rQl' . - 'AjmgMowaN5otTXM='; - $csr = base64_decode($csr); - - $x509 = new X509(); - - $csr = $x509->loadCSR($csr); - - $this->assertInternalType('array', $csr); - } } diff --git a/tests/Unit/File/X509/SPKACTest.php b/tests/Unit/File/X509/SPKACTest.php index 41ff2a0d..29eeebda 100644 --- a/tests/Unit/File/X509/SPKACTest.php +++ b/tests/Unit/File/X509/SPKACTest.php @@ -48,9 +48,10 @@ class Unit_File_X509_SPKACTest extends PhpseclibTestCase { $privKey = new RSA(); extract($privKey->createKey()); + $privKey->loadKey($privatekey); $x509 = new X509(); - $x509->setPrivateKey($privatekey); + $x509->setPrivateKey($privKey); $x509->setChallenge('...'); $spkac = $x509->signSPKAC(); @@ -93,5 +94,6 @@ class Unit_File_X509_SPKACTest extends PhpseclibTestCase $x509->validateSignature(), 'Failed asserting that the signature is invalid' ); + } } diff --git a/tests/Unit/File/X509/X509Test.php b/tests/Unit/File/X509/X509Test.php index 3a2af7cd..06c8efb3 100644 --- a/tests/Unit/File/X509/X509Test.php +++ b/tests/Unit/File/X509/X509Test.php @@ -12,55 +12,6 @@ use phpseclib\Crypt\RSA; class Unit_File_X509_X509Test extends PhpseclibTestCase { - public function testExtensionMapping() - { - $test = '-----BEGIN CERTIFICATE----- -MIIG1jCCBL6gAwIBAgITUAAAAA0qg8bE6DhrLAAAAAAADTANBgkqhkiG9w0BAQsF -ADAiMSAwHgYDVQQDExcuU2VjdXJlIEVudGVycHJpc2UgQ0EgMTAeFw0xNTAyMjMx -NTE1MDdaFw0xNjAyMjMxNTE1MDdaMD8xFjAUBgoJkiaJk/IsZAEZFgZzZWN1cmUx -DjAMBgNVBAMTBVVzZXJzMRUwEwYDVQQDEwxtZXRhY2xhc3NpbmcwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMdG1CzR/gTalbLN9J+2cvMGeD7wsR7S78 -HU5hdwE+kECROjRAcjFBOR57ezSDrkmhkTzo28tj0oAHjOh8N9vuXtASfZSCXugx -H+ImJ+E7PA4aXBp+0H2hohW9sXNNCFiVNmJLX66O4bxIeKtVRq/+eSNijV4OOEkC -zMyTHAUbOFP0t6KoJtM1syNoQ1+fKdfcjz5XtiEzSVcp2zf0MwNFSeZSgGQ0jh8A -Kd6YVKA8ZnrqOWZxKETT+bBNTjIT0ggjQfzcE4zW2RzrN7zWabUowoU92+DAp4s3 -sAEywX9ISSge62DEzTnZZSf9bpoScAfT8raRFA3BkoJ/s4c4CgfPAgMBAAGjggLm -MIIC4jAdBgNVHQ4EFgQULlIyJL9+ZwAI/SkVdsJMxFOVp+EwHwYDVR0jBBgwFoAU -5nEIMEUT5mMd1WepmviwgK7dIzwwggEKBgNVHR8EggEBMIH+MIH7oIH4oIH1hoG5 -bGRhcDovLy9DTj0uU2VjdXJlJTIwRW50ZXJwcmlzZSUyMENBJTIwMSxDTj1hdXRo -LENOPUNEUCxDTj1QdWJsaWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxD -Tj1Db25maWd1cmF0aW9uLERDPXNlY3VyZT9jZXJ0aWZpY2F0ZVJldm9jYXRpb25M -aXN0P2Jhc2U/b2JqZWN0Q2xhc3M9Y1JMRGlzdHJpYnV0aW9uUG9pbnSGN2h0dHA6 -Ly9jcmwuc2VjdXJlb2JzY3VyZS5jb20vP2FjdGlvbj1jcmwmY2E9ZW50ZXJwcmlz -ZTEwgccGCCsGAQUFBwEBBIG6MIG3MIG0BggrBgEFBQcwAoaBp2xkYXA6Ly8vQ049 -LlNlY3VyZSUyMEVudGVycHJpc2UlMjBDQSUyMDEsQ049QUlBLENOPVB1YmxpYyUy -MEtleSUyMFNlcnZpY2VzLENOPVNlcnZpY2VzLENOPUNvbmZpZ3VyYXRpb24sREM9 -c2VjdXJlP2NBQ2VydGlmaWNhdGU/YmFzZT9vYmplY3RDbGFzcz1jZXJ0aWZpY2F0 -aW9uQXV0aG9yaXR5MBcGCSsGAQQBgjcUAgQKHggAVQBzAGUAcjAOBgNVHQ8BAf8E -BAMCBaAwKQYDVR0lBCIwIAYKKwYBBAGCNwoDBAYIKwYBBQUHAwQGCCsGAQUFBwMC -MC4GA1UdEQQnMCWgIwYKKwYBBAGCNxQCA6AVDBNtZXRhY2xhc3NpbmdAc2VjdXJl -MEQGCSqGSIb3DQEJDwQ3MDUwDgYIKoZIhvcNAwICAgCAMA4GCCqGSIb3DQMEAgIA -gDAHBgUrDgMCBzAKBggqhkiG9w0DBzANBgkqhkiG9w0BAQsFAAOCAgEAKNmjYh+h -cObJEM0CWgz50jOYKZ4M5iIxoAWgrYY9Pv+0O9aPjvPLzjd5bY322L8lxh5wy5my -DKmip+irzjdVdxzQfoyy+ceODmCbX9L6MfEDn0RBzdwjLe1/eOxE1na0sZztrVCc -yt5nI91NNGZJUcVqVQsIA/25FWlkvo/FTfuqTuXdQiEVM5MCKJI915anmTdugy+G -0CmBJALIxtyz5P7sZhaHZFNdpKnx82QsauErqjP9H0RXc6VXX5qt+tEDvYfSlFcc -0lv3aQnV/eIdfm7APJkQ3lmNWWQwdkVf7adXJ7KAAPHSt1yvSbVxThJR/jmIkyeQ -XW/TOP5m7JI/GrmvdlzI1AgwJ+zO8fOmCDuif99pDb1CvkzQ65RZ8p5J1ZV6hzlb -VvOhn4LDnT1jnTcEqigmx1gxM/5ifvMorXn/ItMjKPlb72vHpeF7OeKE8GHsvZAm -osHcKyJXbTIcXchmpZX1efbmCMJBqHgJ/qBTBMl9BX0+YqbTZyabRJSs9ezbTRn0 -oRYl21Q8EnvS71CemxEUkSsKJmfJKkQNCsOjc8AbX/V/X9R7LJkH3UEx6K2zQQKK -k6m17mi63YW/+iPCGOWZ2qXmY5HPEyyF2L4L4IDryFJ+8xLyw3pH9/yp5aHZDtp6 -833K6qyjgHJT+fUzSEYpiwF5rSBJIGClOCY= ------END CERTIFICATE-----'; - - $x509 = new X509(); - - $cert = $x509->loadX509($test); - - $this->assertInternalType('array', $cert['tbsCertificate']['extensions'][3]['extnValue']); - } - public function testLoadUnsupportedExtension() { $test = '-----BEGIN CERTIFICATE----- @@ -154,7 +105,7 @@ IOkKcGQRCMha8X2e7GmlpdWC1ycenlbN0nbVeSv3JUMcafC4+Q== public function testSaveNullRSAParam() { $privKey = new RSA(); - $privKey->load('-----BEGIN RSA PRIVATE KEY----- + $privKey->loadKey('-----BEGIN RSA PRIVATE KEY----- MIICXQIBAAKBgQDMswfEpAgnUDWA74zZw5XcPsWh1ly1Vk99tsqwoFDkLF7jvXy1 dDLHYfuquvfxCgcp8k/4fQhx4ubR8bbGgEq9B05YRnViK0R0iBB5Ui4IaxWYYhKE 8xqAEH2fL+/7nsqqNFKkEN9KeFwc7WbMY49U2adlMrpBdRjk1DqIEW3QTwIDAQAB @@ -171,7 +122,7 @@ aBtsWpliLSex/HHhtRW9AkBGcq67zKmEpJ9kXcYLEjJii3flFS+Ct/rNm+Hhm1l7 -----END RSA PRIVATE KEY-----'); $pubKey = new RSA(); - $pubKey->load($privKey->getPublicKey()); + $pubKey->loadKey($privKey->getPublicKey()); $pubKey->setPublicKey(); $subject = new X509(); @@ -217,47 +168,4 @@ aBtsWpliLSex/HHhtRW9AkBGcq67zKmEpJ9kXcYLEjJii3flFS+Ct/rNm+Hhm1l7 } return $value; } - - public function testGetOID() - { - $x509 = new X509(); - $this->assertEquals($x509->getOID('2.16.840.1.101.3.4.2.1'), '2.16.840.1.101.3.4.2.1'); - $this->assertEquals($x509->getOID('id-sha256'), '2.16.840.1.101.3.4.2.1'); - $this->assertEquals($x509->getOID('zzz'), 'zzz'); - } - - public function testIPAddressSubjectAltNamesDecoding() - { - $test = '-----BEGIN CERTIFICATE----- -MIIEcTCCAlmgAwIBAgIBDjANBgkqhkiG9w0BAQsFADAfMR0wGwYDVQQDDBQuU2Vj -dXJlIElzc3VpbmcgQ0EgMTAeFw0xNjAxMjUyMzIwMjZaFw0yMTAxMjYyMzIwMjZa -MBoxGDAWBgNVBAMMDzIwNC4xNTIuMjAwLjI1MDCCASIwDQYJKoZIhvcNAQEBBQAD -ggEPADCCAQoCggEBAM9lMPiYQ26L5qXR1rlUXM0Z3DeRhDsJ/9NadLFJnvxKCV5L -M9rlrThpK6V5VbgPgEwKVLXGtJoGSEUkLd4roJ25ZTH08GcYszWyp8nLPQRovYnN -+aeE1aefnHcpt524f0Es9NFXh0uwRWV3ZCWSwN+mo9Qo6507KZq+q34if7/q9+De -O5RJumVQWc9OCjCt6pQBnBua9oCAca+SIHftOdgWXqVw+Xvl6/dLeF70jJD43P00 -+bdAnGDgBdgO+p+K+XrOCaCWMcCsRX5xiK4hUG54UM5ayBST+McyfjsKxpO2djPg -FlSL0RLg+Nj8WehANUUuaNU874Pp3FV5GTI0ZbUCAwEAAaOBvDCBuTAMBgNVHRMB -Af8EAjAAMAsGA1UdDwQEAwIF4DATBgNVHSUEDDAKBggrBgEFBQcDATAhBgNVHREE -GjAYhwTMmMj6hxAgAQRw8wkACQAAAAAAAAADMEMGA1UdHwQ8MDowOKA2oDSGMmh0 -dHA6Ly9jcmwuc2VjdXJlb2JzY3VyZS5jb20vP2FjdGlvbj1jcmwmY2E9aXNzdWUx -MB8GA1UdIwQYMBaAFOJWVCX4poZSBzemgihf9dAhFNHJMA0GCSqGSIb3DQEBCwUA -A4ICAQAce9whx4InRtzk1to6oeRxTCbeNDjNFuTkotphSws4hDoaz3nyFLSYyMT4 -aKFnNP9AmMS5nEXphtP4HP9wAluTcAFMuip0rDJjiRA/khIE27KurO6cg1faFWHl -6lh6xnEf9UFZZzTLsXt2miBiMb8olgPrBuVFWjPZ/ConesJRZRFqMd5mfntXC+2V -zRcXdtwp9h/Am/WuvjsG/gBAPdeRNKffCokIcgfvffd2oklSDD0T9baG2MTgaxnX -oG6e5saWjoN8bLWuCJpvjA7aErXQwXUyXx1nrTWQ1TCR2N+M62X7e07jZLKSAECP -v6SqZ9/LDmCacVQbfg4wDC/gbpjDSKaD5fkusH6leXleWQ7X8Z03LsKvVq43a71z -jO61kkiFAh3CegWsY+TSYjZxDq58xGMiE7y/fK+SHQXDLyY7HU4eky2l3DSy8bXQ -p64vTJ/OmAcXVNUASfBCNw0kpxuFjlxers/+6zheowB1RIKo0xvSRC4cEDRl/jFA -b7WUT/MIe6B1r0v1gxHnFG2bFI/MhTT9V+tICOLo7+69z4jf/OFkzjYvqq2QWPgc -sE3f2TNnmKFRJx67bEMoaaWLIR94Yuq/TWB6dTiWwk9meZkGG3OjQg/YbO6vl/Am -NDEuGt30Vl2de7G1glnhaceB6Q9KfH7p2gAwNP9JMTtx3PtEcA== ------END CERTIFICATE-----'; - - $x509 = new X509(); - $cert = $x509->loadX509($test); - $this->assertEquals($cert['tbsCertificate']['extensions'][3]['extnValue'][0]['iPAddress'], '204.152.200.250'); - $this->assertEquals($cert['tbsCertificate']['extensions'][3]['extnValue'][1]['iPAddress'], '2001:470:f309:9::3'); - } } diff --git a/tests/Unit/Math/BigInteger/InternalOpenSSLTest.php b/tests/Unit/Math/BigInteger/InternalOpenSSLTest.php index d5056b87..495401fd 100644 --- a/tests/Unit/Math/BigInteger/InternalOpenSSLTest.php +++ b/tests/Unit/Math/BigInteger/InternalOpenSSLTest.php @@ -9,7 +9,7 @@ class Unit_Math_BigInteger_InternalOpenSSLTest extends Unit_Math_BigInteger_Test { public static function setUpBeforeClass() { - if (!extension_loaded('openssl')) { + if (!function_exists('openssl_public_encrypt')) { self::markTestSkipped('openssl_public_encrypt() function is not available.'); } diff --git a/tests/Unit/Math/BigInteger/TestCase.php b/tests/Unit/Math/BigInteger/TestCase.php index 8226c0b5..e417b059 100644 --- a/tests/Unit/Math/BigInteger/TestCase.php +++ b/tests/Unit/Math/BigInteger/TestCase.php @@ -9,7 +9,10 @@ abstract class Unit_Math_BigInteger_TestCase extends PhpseclibTestCase { public static function setUpBeforeClass() { + include_once 'Math/BigInteger.php'; + parent::setUpBeforeClass(); + self::reRequireFile('Math/BigInteger.php'); } @@ -49,7 +52,7 @@ abstract class Unit_Math_BigInteger_TestCase extends PhpseclibTestCase public function testToHex() { - $this->assertSame('41', $this->getInstance('65')->toHex()); + $this->assertSame('41', $this->getInstance('65')->toHex()); } public function testToBits() @@ -217,11 +220,6 @@ abstract class Unit_Math_BigInteger_TestCase extends PhpseclibTestCase $z = $this->getInstance('11111111111111111111111', 16); $this->assertSame($z->toHex(), $x->bitwise_NOT()->toHex()); - - $a = $this->getInstance(0); - $a->bitwise_not(); - - $this->assertSame($a->toString(), '0'); } public function testBitwiseLeftShift() @@ -273,13 +271,29 @@ abstract class Unit_Math_BigInteger_TestCase extends PhpseclibTestCase $min = $this->getInstance(0); $max = $this->getInstance('18446744073709551616'); - $rand1 = \phpseclib\Math\BigInteger::random($min, $max); + $rand1 = $min->random($min, $max); // technically $rand1 can equal $min but with the $min and $max we've // chosen it's just not that likely $this->assertTrue($rand1->compare($min) > 0); $this->assertTrue($rand1->compare($max) < 0); } + public function testRandomOneArgument() + { + $min = $this->getInstance(0); + $max = $this->getInstance('18446744073709551616'); + + $rand1 = $min->random($max); + $this->assertTrue($rand1->compare($min) > 0); + $this->assertTrue($rand1->compare($max) < 0); + + $rand2 = $max->random($min); + $this->assertTrue($rand2->compare($min) > 0); + $this->assertTrue($rand2->compare($max) < 0); + + $this->assertFalse($rand1->equals($rand2)); + } + /** * @group github279 */ @@ -315,8 +329,8 @@ abstract class Unit_Math_BigInteger_TestCase extends PhpseclibTestCase Code for generation of $alicePrivate and $bobPrivate. $one = $this->getInstance(1); $max = $one->bitwise_leftShift(512)->subtract($one); - $alicePrivate = \phpseclib\Math\BigInteger::random($one, $max); - $bobPrivate = \phpseclib\Math\BigInteger::random($one, $max); + $alicePrivate = $one->random($one, $max); + $bobPrivate = $one->random($one, $max); var_dump($alicePrivate->toHex(), $bobPrivate->toHex()); */ @@ -344,40 +358,4 @@ abstract class Unit_Math_BigInteger_TestCase extends PhpseclibTestCase 'Failed asserting that Alice and Bob share the same BigInteger.' ); } - - /** - * @requires PHP 5.6 - */ - public function testDebugInfo() - { - $num = $this->getInstance(50); - $str = print_r($num, true); - $this->assertContains('[value] => 0x32', $str); - } - - public function testPrecision() - { - $a = $this->getInstance(51); - $this->assertSame($a->getPrecision(), -1); - $b = $a; - $c = clone $a; - $b->setPrecision(1); - $this->assertSame($a->getPrecision(), 1); - $this->assertSame("$a", '1'); - $this->assertSame($b->getPrecision(), 1); - $this->assertSame("$b", '1'); - $this->assertSame($c->getPrecision(), -1); - $this->assertSame("$c", '51'); - } - - /** - * @group github954 - */ - public function testSlidingWindow() - { - $e = $this->getInstance(str_repeat('1', 1794), 2); - $x = $this->getInstance(1); - $n = $this->getInstance(2); - $x->powMod($e, $n); - } } diff --git a/tests/Unit/Net/SSH2Test.php b/tests/Unit/Net/SSH2Test.php index 1d3c6439..df9651af 100644 --- a/tests/Unit/Net/SSH2Test.php +++ b/tests/Unit/Net/SSH2Test.php @@ -110,18 +110,6 @@ class Unit_Net_SSH2Test extends PhpseclibTestCase $this->assertFalse($ssh->isQuietModeEnabled()); } - public function testGetConnectionByResourceId() - { - $ssh = new \phpseclib\Net\SSH2('localhost'); - $this->assertSame($ssh, \phpseclib\Net\SSH2::getConnectionByResourceId($ssh->getResourceId())); - } - - public function testGetResourceId() - { - $ssh = new \phpseclib\Net\SSH2('localhost'); - $this->assertSame('{' . spl_object_hash($ssh) . '}', $ssh->getResourceId()); - } - /** * @return \phpseclib\Net\SSH2 */ diff --git a/tests/bootstrap.php b/tests/bootstrap.php index bb137e4d..2472d3b2 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -10,7 +10,7 @@ date_default_timezone_set('UTC'); $loader_path = __DIR__ . '/../vendor/autoload.php'; if (!file_exists($loader_path)) { echo "Dependencies must be installed using composer:\n\n"; - echo "php composer.phar install\n\n"; + echo "php composer.phar install --dev\n\n"; echo "See http://getcomposer.org for help with installing composer\n"; exit(1); } diff --git a/travis/install-php-extensions.sh b/travis/install-php-extensions.sh index 5244261c..2acfdfd7 100755 --- a/travis/install-php-extensions.sh +++ b/travis/install-php-extensions.sh @@ -21,5 +21,10 @@ function install_php_extension } # runkit -git clone https://github.com/zenovich/runkit.git +if [ "$TRAVIS_PHP_VERSION" == "5.6" ] +then + git clone https://github.com/adrianguenter/runkit.git +else + git clone https://github.com/zenovich/runkit.git +fi install_php_extension 'runkit' diff --git a/travis/run-phpunit.sh b/travis/run-phpunit.sh index 5ee69d66..600a1d94 100755 --- a/travis/run-phpunit.sh +++ b/travis/run-phpunit.sh @@ -20,7 +20,7 @@ then PHPUNIT_ARGS="$PHPUNIT_ARGS -d zend.enable_gc=0" fi -if [ "$TRAVIS_PHP_VERSION" = 'hhvm' -o "$TRAVIS_PHP_VERSION" = '7.0' ] +if [ "$TRAVIS_PHP_VERSION" = 'hhvm' ] then find tests -type f -name "*Test.php" | \ parallel --gnu --keep-order \