可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I've an error in my project with Travis CI:
Argon2i algorithm is not supported. Please install the libsodium extension
or upgrade to PHP 7.2+.
But, Argon2i is present in the PHP 7.2 version and Travis CI install the PHP 7.2 version:
$ phpenv global 7.2 2>/dev/null 7.2 is not pre-installed; installing Downloading archive: https://s3.amazonaws.com/travis-php-archives/binaries/ubuntu/14.04/x86_64/php-7.2.tar.bz2 $ curl -s -o archive.tar.bz2 $archive_url && tar xjf archive.tar.bz2 --directory / $ phpenv global 7.2 $ php --version PHP 7.2.0 (cli) (built: Dec 2 2017 17:12:55) ( ZTS ) Copyright (c) 1997-2017 The PHP Group Zend Engine v3.2.0, Copyright (c) 1998-2017 Zend Technologies with Zend OPcache v7.2.0, Copyright (c) 1999-2017, by Zend Technologies with Xdebug v2.6.0-dev, Copyright (c) 2002-2017, by Derick Rethans
Someone have an idea ?
回答1:
I faced the same problem recently in a Symfony 4 project and posted an issue on Travis' Github.
However, the problem does not seem to come from Travis but from PHP 7.2 default build itself.
Quoting myself:
I was locally using a pre-configured PHP, so to be sure I just compiled PHP 7.2 from sources.
$ ./php -v PHP 7.2.0 (cli) (built: Dec 6 2017 15:26:29) ( NTS ) Copyright (c) 1997-2017 The PHP Group Zend Engine v3.2.0, Copyright (c) 1998-2017 Zend Technologies
Then I tryed to use the ARGON2I
algorithm such as described in official docs:
$ ./php -r 'echo password_hash("test", PASSWORD_ARGON2I) . "\n";' Warning: Use of undefined constant PASSWORD_ARGON2I - assumed 'PASSWORD_ARGON2I' (this will throw an Error in a future version of PHP) in Command line code on line 1 Warning: password_hash() expects parameter 2 to be integer, string given in Command line code on line 1
While not having any problem with BCRYPT
:
$ ./php -r 'echo password_hash("test", PASSWORD_BCRYPT) . "\n";' $2y$10$wsWe3BhyzenVqDs6JV/fPOB0XKh0oTuGdrgLp61MnUPzOUdw4jZey
This is strange. I would have expected this algorithm to be part of the default PHP 7.2 build, just as other hash algorithms. And nothing seems to indicate the opposite in the docs. I'll investigate. Maybe I understood something wrong... but this looks like a bug to me, since they say here that PASSWORD_ARGON2I
is part of PHP core.
Edit:
In the light of Sheppard's comment, it appears indeed that 7.2 does not implement the PASSWORD_AGRON2I
algorithm in its default build. PHP has to be compiled with option -with-password-argon2
, such as described in https://wiki.php.net/rfc/argon2_password_hash.
回答2:
It appear PHP 7.2 haven't argon2i password hasher by default, it's a compile option, but TravisCi don't use it in their PHP images, then we can avoid this error by adding a library (initially used in PHP < 7.2 versions) as mensionned in https://symfony.com/blog/new-in-symfony-3-4-argon2i-password-hasher, but not in our composer.json directly, call it in .travis.yml file:
before_install: # Fix Argon2i password hasher in TravisCi PHP version - composer require paragonie/sodium_compat
EDIT:
Because Symfony has been updated, the previous solution no longer works, then I choose to directly add the libsodium extension with PECL. This method is better I think, because we install and enable the PHP extension.
We must download sources of the libsodium library because ubuntu 14.04 haven't the library, then compile it, and compile the PHP extension with pecl, and enable it.
It works well, but it take more time than the previous solution.
回答3:
This is indeed a silly dropped-ball by PHP. Fortunately there is a reasonable workaround - while libargon2 is not compiled in by default (because it's not available on all the platforms that PHP is), libsodium is, and though libsodium doesn't provide the PASSWORD_ARGON2I
constant, it has the sodium_crypto_pwhash
function, which uses the Argon2id variant of the Argon2 password hashing algorithm, which is stronger than the stock PHP 7.2 Argon2i, but is not compatible with it. You use it like this:
$hash = sodium_crypto_pwhash_str( $password, SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE, SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE );
You can get this function in PHP versions prior to PHP 7.2 using the paragonie/sodium_compat
library via composer.
I think transparent fallback through this was a missed opportunity in Symfony - it ends up failing to provide an implementation in exactly the same way that PHP itself does, which is no help to anyone.