diff --git a/.gitignore b/.gitignore index 2d0575c..987c516 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,11 @@ -test/unit/File/big-generated-file +*~ +/test/unit/File/big-generated-file +/composer.lock +/vendor +defuse-crypto.phar +defuse-crypto.phar.sig +composer.phar +box.phar +phpunit.phar +phpunit.phar.asc +test/unit/File/tmp diff --git a/.travis.yml b/.travis.yml index db09559..2fcff88 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,4 +10,13 @@ sudo: false matrix: fast_finish: true -script: ./test.sh +install: + - composer install + - curl -LSs https://box-project.github.io/box2/installer.php | php + - mkdir ~/box + - mv box.phar ~/box/box + +script: + - ./test.sh + - PATH=$PATH:~/box/ make -C dist/ build-phar + - ./test.sh dist/defuse-crypto.phar diff --git a/autoload.php b/autoload.php deleted file mode 100644 index a13aea2..0000000 --- a/autoload.php +++ /dev/null @@ -1,68 +0,0 @@ - autoloader -> LFI hardening - */ - $classmap = array( - 'Core' => - 'Core.php', - 'Crypto' => - 'Crypto.php', - 'DerivedKeys' => - 'DerivedKeys.php', - 'Encoding' => - 'Encoding.php', - 'ExceptionHandler' => - 'ExceptionHandler.php', - 'File' => - 'File.php', - 'Key' => - 'Key.php', - 'KeyOrPassword' => - 'KeyOrPassword.php', - 'KeyProtectedByPassword' => - 'KeyProtectedByPassword.php', - 'Salt' => - 'Salt.php', - 'RuntimeTests' => - 'RuntimeTests.php', - // Exceptions: - 'Exception\\BadFormatException' => - 'Exception/BadFormatException.php', - 'Exception\\EnvironmentIsBrokenException' => - 'Exception/EnvironmentIsBrokenException.php', - 'Exception\\CryptoException' => - 'Exception/CryptoException.php', - 'Exception\\IOException' => - 'Exception/IOException.php', - 'Exception\\WrongKeyOrModifiedCiphertextException' => - 'Exception/WrongKeyOrModifiedCiphertextException.php', - ); - foreach ($classmap as $classname => $file) { - if ($classname === $relative_class) { - require $base_dir.$file; - } - } -}); diff --git a/composer.json b/composer.json index 62d4f88..c4ae44b 100644 --- a/composer.json +++ b/composer.json @@ -7,15 +7,22 @@ "authors": [ { "name": "Taylor Hornby", - "email": "havoc@defuse.ca" + "email": "taylor@defuse.ca", + "homepage": "https://defuse.ca/" + }, + { + "name": "Scott Arciszewski", + "email": "info@paragonie.com", + "homepage": "https://paragonie.com" } ], "autoload": { - "files": ["autoload.php"] + "classmap": ["src"] }, "require": { - "php": ">=5.4.0", - "ext-openssl": "*" + "paragonie/random_compat": "~2.0", + "ext-openssl": "*", + "php": ">=5.4.0" }, "require-dev": { "nikic/php-parser": "^2.0" diff --git a/dist/Makefile b/dist/Makefile new file mode 100644 index 0000000..15b2494 --- /dev/null +++ b/dist/Makefile @@ -0,0 +1,37 @@ +# This builds defuse-crypto.phar. To run this Makefile, `box` and `composer` +# must be installed and in your $PATH. Run it from inside the dist/ directory. + +box := $(shell which box) +composer := "composer" + +.PHONY: all +all: sign-phar + +.PHONY: sign-phar +sign-phar: build-phar + gpg -u 7B4B2D98 --armor --output defuse-crypto.phar.sig --detach-sig defuse-crypto.phar + +# ensure we run in clean tree. export git tree and run there. +.PHONY: build-phar +build-phar: + @echo "Creating .phar from revision $(shell git rev-parse HEAD)." + rm -rf worktree + install -d worktree + (cd $(CURDIR)/..; git archive HEAD) | tar -x -C worktree + $(MAKE) -f $(CURDIR)/Makefile -C worktree defuse-crypto.phar + mv worktree/*.phar . + rm -rf worktree + +.PHONY: clean +clean: + rm -vf defuse-crypto.phar defuse-crypto.phar.sig + +# Inside workdir/: + +defuse-crypto.phar: dist/box.json composer.lock + cp dist/box.json . + php -d phar.readonly=0 $(box) build -c box.json -v + +composer.lock: + $(composer) install --no-dev + diff --git a/dist/box.json b/dist/box.json new file mode 100644 index 0000000..fe74393 --- /dev/null +++ b/dist/box.json @@ -0,0 +1,24 @@ +{ + "chmod": "0755", + "finder": [ + { + "in": "src", + "name": "*.php" + }, + { + "in": "vendor/composer", + "name": "*.php" + }, + { + "in": "vendor/paragonie", + "name": "*.php", + "exclude": "other" + } + ], + "compactors": [ + "Herrera\\Box\\Compactor\\Php" + ], + "main": "vendor/autoload.php", + "output": "defuse-crypto.phar", + "stub": true +} diff --git a/dist/defuse-crypto.phar b/dist/defuse-crypto.phar deleted file mode 100644 index b9986f4..0000000 Binary files a/dist/defuse-crypto.phar and /dev/null differ diff --git a/dist/defuse-crypto.phar.sig b/dist/defuse-crypto.phar.sig deleted file mode 100644 index c935db2..0000000 --- a/dist/defuse-crypto.phar.sig +++ /dev/null @@ -1,17 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v2 - -iQIcBAABCAAGBQJXHEa0AAoJEDhe4FWhKRU4ZS8QAJzo8p9K7UqGyiRMHd4rsV7f -e3fUlr9YHnvrxHKtxBeY/817+lng8d8yc3PdLQHnmUDB04zEbeh+U95ZYZT3Jm9W -6fU8y8n5EzzxZBbkDGeDM+ds/BZZeGjNfl9HUz2huERwNueiASOmpUYLFaWiGziw -ivDiVWISfFnxU9IIeWUUX8wbRO3kL23AuNsRHXnjaL8OWLdZHg+562QaBP8l/vGp -JXSGdknIzb0hHTQgrk/fqMl8S2eHzgl/ZK6xI15RUPWQ85L4wIno5rkeD0jSdPuu -5EoQoBkcdC5H88dBcd6zhnAcBgBRl715jvLbZU+Jr3CQEGWD41MRRSwa7sAPYR1l -MjUdwvU4MVK/VHBbRD2JlgCrR/HXchfWpYwdSIx+2UcF8wEH5nqqRPAi3LTCN+bu -qA6CD9/rQh2dlYEZgq60VoDiXKHPM6kPcpyyIC/iaYgfif4M4reBDu9aVCCmYmwk -33oQ0S+nu0+q7IaQrIY8ohD7lguVloYTqhdysUrWQaEYo+uKaCz6WlZuhJz3RrhX -u5lNTeajWKXhPGhBfE0prQ6kdGfMGEb5iV9JxzM1f/9nq2ow5fg1QtBmKcegNP52 -FKU29BM6DU82dOUckJY+KICgQ2XWka+Laqj1x26a2Hml+xx3eiSmHQjO+v6CvZfo -Am8gGvNnyc6DgDKXVXzN -=BZoQ ------END PGP SIGNATURE----- diff --git a/other/signingkey.asc b/dist/signingkey.asc similarity index 100% rename from other/signingkey.asc rename to dist/signingkey.asc diff --git a/docs/InstallingAndVerifying.md b/docs/InstallingAndVerifying.md index 640a3b0..e68f762 100644 --- a/docs/InstallingAndVerifying.md +++ b/docs/InstallingAndVerifying.md @@ -4,7 +4,7 @@ Getting The Code There are two ways to use this library in your applications. You can either: 1. Use [Composer](https://getcomposer.org/), or -2. `require_once()` a single `.phar` file in your application. +2. `require_once` a single `.phar` file in your application. Option 1: Using Composer ------------------------- @@ -23,16 +23,20 @@ Option 2: Including a PHAR ---------------------------- The `.phar` option lets you include this library into your project simply by -calling `require_once()` on a single file. Simply check out the tag with the -version you want, for example for version 2.0.0 you would do: - -``` -git checkout v2.0.0 -``` +calling `require_once` on a single file. Download `defuse-crypto.phar` and +`defuse-crypto.phar.sig` from this project's +[releases](https://github.com/defuse/php-encryption/releases) page. + +You should verify the integrity of the `.phar`. The `defuse-crypto.phar.sig` +contains the signature of `defuse-crypto.phar`. It is signed with Taylor +Hornby's PGP key. You can find Taylor's public key in `dist/signingkey.asc`. You +can verify the public key's fingerprint against the Taylor Hornby's [contact +page](https://defuse.ca/contact.htm) and +[twitter](https://twitter.com/DefuseSec/status/723741424253059074). -You'll find the `.phar` file for that release in `dist/defuse-crypto.phar`. -Install it to somewhere on your filesystem, e.g. -`/var/www/lib/defuse-crypto.phar`. You can now use it in your code like this: +Once you have verified the signature, it is safe to use the `.phar`. Place it +somewhere in your file system, e.g. `/var/www/lib/defuse-crypto.phar`, and then +pass that path to `require_once`. ```php ``` -Run the sign-release script (note this will make a commit on your current -branch): +Generate and sign the `.phar`: ``` -./other/sign-release.sh +cd dist +make ``` -Push the branch and tag up to GitHub. +Tag the release: + +``` +git -c user.signingkey=7B4B2D98 tag -s "" -m "" +``` + +`` should be in the format `v2.0.0` and `` should look +like "Release of v2.0.0." + +Push the tag to github, then use the +[releases](https://github.com/defuse/php-encryption/releases) page to draft +a new release for that tag. Upload the `.phar` and the `.phar.sig` file to be +included as part of that release. diff --git a/other/build-phar.sh b/other/build-phar.sh deleted file mode 100755 index aa20926..0000000 --- a/other/build-phar.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env bash - -basedir=$( dirname $( readlink -f ${BASH_SOURCE[0]} ) ) - -cp ./autoload.php ./src/index.php -sed -i "s/__DIR__.'\/src\/'/'phar:\/\/defuse-crypto.phar\/'/" ./src/index.php - -php -dphar.readonly=0 "$basedir/build_phar.php" $* - -rm ./src/index.php diff --git a/other/build_phar.php b/other/build_phar.php deleted file mode 100755 index f9bfea0..0000000 --- a/other/build_phar.php +++ /dev/null @@ -1,51 +0,0 @@ -buildFromDirectory(dirname(__DIR__) . '/src'); - -/** - * If we pass an (optional) path to a private key as a second argument, we will - * sign the Phar with OpenSSL. - * - * If you leave this out, it will produce an unsigned .phar! - */ -if ($argc > 1) { - if (! @\is_readable($argv[1])) { - echo 'Could not read the private key file:', $argv[1], "\n"; - exit(255); - } - $pkeyFile = \file_get_contents($argv[1]); - - $private = \openssl_get_privatekey($pkeyFile); - if ($private !== false) { - $pkey = ''; - \openssl_pkey_export($private, $pkey); - $phar->setSignatureAlgorithm(\Phar::OPENSSL, $pkey); - - /** - * Save the corresponding public key to the file - */ - if (! @\is_readable($dist . '/defuse-crypto.phar.pubkey')) { - $details = \openssl_pkey_get_details($private); - \file_put_contents( - $dist . '/defuse-crypto.phar.pubkey', - $details['key'] - ); - } - } else { - echo 'An error occurred reading the private key from OpenSSL.', "\n"; - exit(255); - } -} diff --git a/other/sign-release.sh b/other/sign-release.sh deleted file mode 100755 index 0455e18..0000000 --- a/other/sign-release.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -set -e - -current_repo_has_unsaved_changes () { - if git diff --exit-code && ! [[ $(git clean -dfx --dry-run) ]]; then - return 1 - else - return 0 - fi -} - -if current_repo_has_unsaved_changes; then - echo "It's best to run this from a fresh clone." - exit 1 -fi - -./other/build-phar.sh -./test.sh dist/defuse-crypto.phar -gpg -u 7B4B2D98 --armor --output dist/defuse-crypto.phar.sig --detach-sig dist/defuse-crypto.phar - -git add dist -git commit -m "Automatic commit of dist/" - -git -c user.signingkey=7B4B2D98 tag -s "$1" -m "$2" diff --git a/src/random_compat/byte_safe_strings.php b/src/random_compat/byte_safe_strings.php deleted file mode 100644 index dec5d30..0000000 --- a/src/random_compat/byte_safe_strings.php +++ /dev/null @@ -1,181 +0,0 @@ - RandomCompat_strlen($binary_string)) { - return false; - } - - return mb_substr($binary_string, $start, $length, '8bit'); - } - - } else { - - /** - * substr() implementation that isn't brittle to mbstring.func_overload - * - * This version just uses the default substr() - * - * @param string $binary_string - * @param int $start - * @param int $length (optional) - * - * @throws TypeError - * - * @return string - */ - function RandomCompat_substr($binary_string, $start, $length = null) - { - if (!is_string($binary_string)) { - throw new TypeError( - 'RandomCompat_substr(): First argument should be a string' - ); - } - - if (!is_int($start)) { - throw new TypeError( - 'RandomCompat_substr(): Second argument should be an integer' - ); - } - - if ($length !== null) { - if (!is_int($length)) { - throw new TypeError( - 'RandomCompat_substr(): Third argument should be an integer, or omitted' - ); - } - - return substr($binary_string, $start, $length); - } - - return substr($binary_string, $start); - } - } -} diff --git a/src/random_compat/cast_to_int.php b/src/random_compat/cast_to_int.php deleted file mode 100644 index f441c5d..0000000 --- a/src/random_compat/cast_to_int.php +++ /dev/null @@ -1,71 +0,0 @@ - operators might accidentally let a float - * through. - * - * @param int|float $number The number we want to convert to an int - * @param boolean $fail_open Set to true to not throw an exception - * - * @return int (or float if $fail_open) - * - * @throws TypeError - */ - function RandomCompat_intval($number, $fail_open = false) - { - if (is_numeric($number)) { - $number += 0; - } - - if ( - is_float($number) - && - $number > ~PHP_INT_MAX - && - $number < PHP_INT_MAX - ) { - $number = (int) $number; - } - - if (is_int($number) || $fail_open) { - return $number; - } - - throw new TypeError( - 'Expected an integer.' - ); - } -} diff --git a/src/random_compat/error_polyfill.php b/src/random_compat/error_polyfill.php deleted file mode 100644 index 57cfefd..0000000 --- a/src/random_compat/error_polyfill.php +++ /dev/null @@ -1,42 +0,0 @@ -GetRandom() - * 5. openssl_random_pseudo_bytes() (absolute last resort) - * - * See ERRATA.md for our reasoning behind this particular order - */ - if (extension_loaded('libsodium')) { - // See random_bytes_libsodium.php - if (PHP_VERSION_ID >= 50300 && function_exists('\\Sodium\\randombytes_buf')) { - require_once $RandomCompatDIR.'/random_bytes_libsodium.php'; - } elseif (method_exists('Sodium', 'randombytes_buf')) { - require_once $RandomCompatDIR.'/random_bytes_libsodium_legacy.php'; - } - } - - /** - * Reading directly from /dev/urandom: - */ - if (DIRECTORY_SEPARATOR === '/') { - // DIRECTORY_SEPARATOR === '/' on Unix-like OSes -- this is a fast - // way to exclude Windows. - $RandomCompatUrandom = true; - $RandomCompat_basedir = ini_get('open_basedir'); - - if (!empty($RandomCompat_basedir)) { - $RandomCompat_open_basedir = explode( - PATH_SEPARATOR, - strtolower($RandomCompat_basedir) - ); - $RandomCompatUrandom = (array() !== array_intersect( - array('/dev', '/dev/', '/dev/urandom'), - $RandomCompat_open_basedir - )); - $RandomCompat_open_basedir = null; - } - - if ( - !function_exists('random_bytes') - && - $RandomCompatUrandom - && - @is_readable('/dev/urandom') - ) { - // Error suppression on is_readable() in case of an open_basedir - // or safe_mode failure. All we care about is whether or not we - // can read it at this point. If the PHP environment is going to - // panic over trying to see if the file can be read in the first - // place, that is not helpful to us here. - - // See random_bytes_dev_urandom.php - require_once $RandomCompatDIR.'/random_bytes_dev_urandom.php'; - } - // Unset variables after use - $RandomCompat_basedir = null; - } else { - $RandomCompatUrandom = false; - } - - /** - * mcrypt_create_iv() - */ - if ( - !function_exists('random_bytes') - && - PHP_VERSION_ID >= 50307 - && - extension_loaded('mcrypt') - && - (DIRECTORY_SEPARATOR !== '/' || $RandomCompatUrandom) - ) { - // Prevent this code from hanging indefinitely on non-Windows; - // see https://bugs.php.net/bug.php?id=69833 - if ( - DIRECTORY_SEPARATOR !== '/' || - (PHP_VERSION_ID <= 50609 || PHP_VERSION_ID >= 50613) - ) { - // See random_bytes_mcrypt.php - require_once $RandomCompatDIR.'/random_bytes_mcrypt.php'; - } - } - $RandomCompatUrandom = null; - - if ( - !function_exists('random_bytes') - && - extension_loaded('com_dotnet') - && - class_exists('COM') - ) { - $RandomCompat_disabled_classes = preg_split( - '#\s*,\s*#', - strtolower(ini_get('disable_classes')) - ); - - if (!in_array('com', $RandomCompat_disabled_classes)) { - try { - $RandomCompatCOMtest = new COM('CAPICOM.Utilities.1'); - if (method_exists($RandomCompatCOMtest, 'GetRandom')) { - // See random_bytes_com_dotnet.php - require_once $RandomCompatDIR.'/random_bytes_com_dotnet.php'; - } - } catch (com_exception $e) { - // Don't try to use it. - } - } - $RandomCompat_disabled_classes = null; - $RandomCompatCOMtest = null; - } - - /** - * throw new Exception - */ - if (!function_exists('random_bytes')) { - /** - * We don't have any more options, so let's throw an exception right now - * and hope the developer won't let it fail silently. - */ - function random_bytes($length) - { - throw new Exception( - 'There is no suitable CSPRNG installed on your system' - ); - } - } - } - - if (!function_exists('random_int')) { - require_once $RandomCompatDIR.'/random_int.php'; - } - - $RandomCompatDIR = null; -} diff --git a/src/random_compat/random_bytes_com_dotnet.php b/src/random_compat/random_bytes_com_dotnet.php deleted file mode 100644 index 3422825..0000000 --- a/src/random_compat/random_bytes_com_dotnet.php +++ /dev/null @@ -1,81 +0,0 @@ -GetRandom($bytes, 0)); - if (RandomCompat_strlen($buf) >= $bytes) { - /** - * Return our random entropy buffer here: - */ - return RandomCompat_substr($buf, 0, $bytes); - } - ++$execCount; - } while ($execCount < $bytes); - - /** - * If we reach here, PHP has failed us. - */ - throw new Exception( - 'Could not gather sufficient random data' - ); -} diff --git a/src/random_compat/random_bytes_dev_urandom.php b/src/random_compat/random_bytes_dev_urandom.php deleted file mode 100644 index db93b07..0000000 --- a/src/random_compat/random_bytes_dev_urandom.php +++ /dev/null @@ -1,148 +0,0 @@ - 0); - - /** - * Is our result valid? - */ - if ($buf !== false) { - if (RandomCompat_strlen($buf) === $bytes) { - /** - * Return our random entropy buffer here: - */ - return $buf; - } - } - } - - /** - * If we reach here, PHP has failed us. - */ - throw new Exception( - 'Error reading from source device' - ); -} diff --git a/src/random_compat/random_bytes_libsodium.php b/src/random_compat/random_bytes_libsodium.php deleted file mode 100644 index f802d4e..0000000 --- a/src/random_compat/random_bytes_libsodium.php +++ /dev/null @@ -1,86 +0,0 @@ - 2147483647) { - $buf = ''; - for ($i = 0; $i < $bytes; $i += 1073741824) { - $n = ($bytes - $i) > 1073741824 - ? 1073741824 - : $bytes - $i; - $buf .= \Sodium\randombytes_buf($n); - } - } else { - $buf = \Sodium\randombytes_buf($bytes); - } - - if ($buf !== false) { - if (RandomCompat_strlen($buf) === $bytes) { - return $buf; - } - } - - /** - * If we reach here, PHP has failed us. - */ - throw new Exception( - 'Could not gather sufficient random data' - ); -} diff --git a/src/random_compat/random_bytes_libsodium_legacy.php b/src/random_compat/random_bytes_libsodium_legacy.php deleted file mode 100644 index 44fddbf..0000000 --- a/src/random_compat/random_bytes_libsodium_legacy.php +++ /dev/null @@ -1,86 +0,0 @@ - 2147483647) { - $buf = ''; - for ($i = 0; $i < $bytes; $i += 1073741824) { - $n = ($bytes - $i) > 1073741824 - ? 1073741824 - : $bytes - $i; - $buf .= Sodium::randombytes_buf($n); - } - } else { - $buf = Sodium::randombytes_buf($bytes); - } - - if ($buf !== false) { - if (RandomCompat_strlen($buf) === $bytes) { - return $buf; - } - } - - /** - * If we reach here, PHP has failed us. - */ - throw new Exception( - 'Could not gather sufficient random data' - ); -} diff --git a/src/random_compat/random_bytes_mcrypt.php b/src/random_compat/random_bytes_mcrypt.php deleted file mode 100644 index 7ac9d91..0000000 --- a/src/random_compat/random_bytes_mcrypt.php +++ /dev/null @@ -1,76 +0,0 @@ - operators might accidentally let a float - * through. - */ - - try { - $min = RandomCompat_intval($min); - } catch (TypeError $ex) { - throw new TypeError( - 'random_int(): $min must be an integer' - ); - } - - try { - $max = RandomCompat_intval($max); - } catch (TypeError $ex) { - throw new TypeError( - 'random_int(): $max must be an integer' - ); - } - - /** - * Now that we've verified our weak typing system has given us an integer, - * let's validate the logic then we can move forward with generating random - * integers along a given range. - */ - if ($min > $max) { - throw new Error( - 'Minimum value must be less than or equal to the maximum value' - ); - } - - if ($max === $min) { - return $min; - } - - /** - * Initialize variables to 0 - * - * We want to store: - * $bytes => the number of random bytes we need - * $mask => an integer bitmask (for use with the &) operator - * so we can minimize the number of discards - */ - $attempts = $bits = $bytes = $mask = $valueShift = 0; - - /** - * At this point, $range is a positive number greater than 0. It might - * overflow, however, if $max - $min > PHP_INT_MAX. PHP will cast it to - * a float and we will lose some precision. - */ - $range = $max - $min; - - /** - * Test for integer overflow: - */ - if (!is_int($range)) { - - /** - * Still safely calculate wider ranges. - * Provided by @CodesInChaos, @oittaa - * - * @ref https://gist.github.com/CodesInChaos/03f9ea0b58e8b2b8d435 - * - * We use ~0 as a mask in this case because it generates all 1s - * - * @ref https://eval.in/400356 (32-bit) - * @ref http://3v4l.org/XX9r5 (64-bit) - */ - $bytes = PHP_INT_SIZE; - $mask = ~0; - - } else { - - /** - * $bits is effectively ceil(log($range, 2)) without dealing with - * type juggling - */ - while ($range > 0) { - if ($bits % 8 === 0) { - ++$bytes; - } - ++$bits; - $range >>= 1; - $mask = $mask << 1 | 1; - } - $valueShift = $min; - } - - /** - * Now that we have our parameters set up, let's begin generating - * random integers until one falls between $min and $max - */ - do { - /** - * The rejection probability is at most 0.5, so this corresponds - * to a failure probability of 2^-128 for a working RNG - */ - if ($attempts > 128) { - throw new Exception( - 'random_int: RNG is broken - too many rejections' - ); - } - - /** - * Let's grab the necessary number of random bytes - */ - $randomByteString = random_bytes($bytes); - if ($randomByteString === false) { - throw new Exception( - 'Random number generator failure' - ); - } - - /** - * Let's turn $randomByteString into an integer - * - * This uses bitwise operators (<< and |) to build an integer - * out of the values extracted from ord() - * - * Example: [9F] | [6D] | [32] | [0C] => - * 159 + 27904 + 3276800 + 201326592 => - * 204631455 - */ - $val = 0; - for ($i = 0; $i < $bytes; ++$i) { - $val |= ord($randomByteString[$i]) << ($i * 8); - } - - /** - * Apply mask - */ - $val &= $mask; - $val += $valueShift; - - ++$attempts; - /** - * If $val overflows to a floating point number, - * ... or is larger than $max, - * ... or smaller than $min, - * then try again. - */ - } while (!is_int($val) || $val > $max || $val < $min); - - return (int) $val; -} diff --git a/test.sh b/test.sh index 0ee8a53..ace184f 100755 --- a/test.sh +++ b/test.sh @@ -10,7 +10,8 @@ fi if [ -n "$1" ]; then BOOTSTRAP="$1" else - BOOTSTRAP="autoload.php" + # You need to run `composer install` to generate this file. + BOOTSTRAP="vendor/autoload.php" fi ./test/phpunit.sh "$BOOTSTRAP"