diff options
author | Marcin Łojewski <marcin.lojewski@mlojewski.me> | 2020-02-02 23:39:51 +0300 |
---|---|---|
committer | Marcin Łojewski <marcin.lojewski@mlojewski.me> | 2020-02-02 23:43:39 +0300 |
commit | 9644bce09c2d21bbe8cbf475c4987a97d9ae82e9 (patch) | |
tree | e3ee8ac2a1f39f5053dea86a24dc6d256c651f6c | |
parent | 973018b63b5294642b1a5ff4cb39cde869e4d00d (diff) |
issue#94 XenForo bcrypt
32 files changed, 222 insertions, 29 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 992be77..d5c76c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added +- Support for Nextcloud 19 +- Argon2id support ## [4.4.1] - 2020-02-02 ### Fixed @@ -191,7 +191,8 @@ Courier hexadecimal MD5 | No salt supported. | {MD5}X03MO1qnZdYdgyfeuILPmQ== Courier base64-encoded SHA1 | No salt supported. | {SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g= Courier base64-encoded SHA256 | No salt supported. | {SHA256}XohImNooBHFR0OVvjcYpJ3NgPQ1qq73WKhHvch0VQtg= Unix (Crypt) | See [crypt](http://php.net/manual/en/function.crypt.php). | $2y$10$5rsN1fmoSkaRy9bqhozAXOr0mn0QiVIfd2L04Bbk1Go9MjdvotwBq -Argon2 (Crypt) | Requires PHP >= 7.2. See [password_hash](http://php.net/manual/en/function.password-hash.php). | $argon2i$v=19$m=1024,t=2,p=2$NnpSNlRNLlZobnJHUDh0Sw$oW5E1cfdPzLWfkTvQFUyzTR00R0aLwEdYwldcqW6Pmo +Argon2i (Crypt) | Requires PHP >= 7.2. See [password_hash](http://php.net/manual/en/function.password-hash.php). | $argon2i$v=19$m=1024,t=2,p=2$NnpSNlRNLlZobnJHUDh0Sw$oW5E1cfdPzLWfkTvQFUyzTR00R0aLwEdYwldcqW6Pmo +Argon2id (Crypt) | Requires PHP >= 7.2. See [password_hash](http://php.net/manual/en/function.password-hash.php). | $argon2id$v=19$m=65536,t=4,p=1$eWhTd3huemlhNGFkWTVSSQ$BjSh9PINc9df9WU1zppBsYJKvkwUEYHYNUUMTj+QGPw Blowfish (Crypt) | See [password_hash](http://php.net/manual/en/function.password-hash.php). | $2y$10$5rsN1fmoSkaRy9bqhozAXOr0mn0QiVIfd2L04Bbk1Go9MjdvotwBq Extended DES (Crypt) | | cDRpdxPmHpzS. MD5 (Crypt) | | $1$RzaFbNcU$u9adfTY/Q6za6nu0Ogrl1/ diff --git a/appinfo/info.xml b/appinfo/info.xml index b4a23b7..bbe8710 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -21,7 +21,7 @@ </types> <category>auth</category> <dependencies> - <php min-version="7.0"/> + <php min-version="7.1"/> <nextcloud min-version="14" max-version="19"/> </dependencies> <settings> diff --git a/lib/Crypto/CryptArgon2.php b/lib/Crypto/CryptArgon2.php index ddbfe0a..ef41cee 100644 --- a/lib/Crypto/CryptArgon2.php +++ b/lib/Crypto/CryptArgon2.php @@ -122,6 +122,6 @@ class CryptArgon2 extends AbstractAlgorithm */ protected function getAlgorithmName() { - return "Argon2 (Crypt)"; + return "Argon2i (Crypt)"; } } diff --git a/lib/Crypto/CryptArgon2id.php b/lib/Crypto/CryptArgon2id.php new file mode 100644 index 0000000..77f610b --- /dev/null +++ b/lib/Crypto/CryptArgon2id.php @@ -0,0 +1,127 @@ +<?php +/** + * Nextcloud - user_sql + * + * @copyright 2020 Marcin Łojewski <dev@mlojewski.me> + * @author Marcin Łojewski <dev@mlojewski.me> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +namespace OCA\UserSQL\Crypto; + +use OCP\IL10N; + +/** + * Argon2id Crypt hash implementation. + * + * @see crypt() + * @author Marcin Łojewski <dev@mlojewski.me> + */ +class CryptArgon2id extends AbstractAlgorithm +{ + /** + * @var int Maximum memory (in bytes) that may be used to compute. + */ + private $memoryCost; + /** + * @var int Maximum amount of time it may take to compute. + */ + private $timeCost; + /** + * @var int Number of threads to use for computing. + */ + private $threads; + + /** + * The class constructor. + * + * @param IL10N $localization The localization service. + * @param int $memoryCost Maximum memory (in bytes) that may be used + * to compute. + * @param int $timeCost Maximum amount of time it may take to compute. + * @param int $threads Number of threads to use for computing. + */ + public function __construct( + IL10N $localization, $memoryCost = -1, $timeCost = -1, $threads = -1 + ) { + if (version_compare(PHP_VERSION, "7.2.0") === -1) { + throw new \RuntimeException( + " PASSWORD_ARGON2ID requires PHP 7.2.0 or above." + ); + } else { + if ($memoryCost === -1) { + $memoryCost = PASSWORD_ARGON2_DEFAULT_MEMORY_COST; + } + if ($timeCost === -1) { + $timeCost = PASSWORD_ARGON2_DEFAULT_TIME_COST; + } + if ($threads === -1) { + $threads = PASSWORD_ARGON2_DEFAULT_THREADS; + } + } + + parent::__construct($localization); + $this->memoryCost = $memoryCost; + $this->timeCost = $timeCost; + $this->threads = $threads; + } + + /** + * @inheritdoc + */ + public function checkPassword($password, $dbHash, $salt = null) + { + return password_verify($password, $dbHash); + } + + /** + * @inheritdoc + */ + public function getPasswordHash($password, $salt = null) + { + return password_hash( + $password, PASSWORD_ARGON2ID, [ + "memory_cost" => $this->memoryCost, + "time_cost" => $this->timeCost, + "threads" => $this->threads + ] + ); + } + + /** + * @inheritdoc + */ + public function configuration() + { + return [ + new CryptoParam( + "Memory cost (KiB)", PASSWORD_ARGON2_DEFAULT_MEMORY_COST, 1, + 1048576 + ), + new CryptoParam( + "Time cost", PASSWORD_ARGON2_DEFAULT_TIME_COST, 1, 1024 + ), + new CryptoParam("Threads", PASSWORD_ARGON2_DEFAULT_THREADS, 1, 1024) + ]; + } + + /** + * @inheritdoc + */ + protected function getAlgorithmName() + { + return "Argon2id (Crypt)"; + } +} diff --git a/tests/Crypto/CleartextTest.php b/tests/Crypto/CleartextTest.php index 67d5547..1987989 100644 --- a/tests/Crypto/CleartextTest.php +++ b/tests/Crypto/CleartextTest.php @@ -49,7 +49,7 @@ class CleartextTest extends TestCase $this->assertTrue($this->crypto->checkPassword("password", $hash)); } - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->crypto = new Cleartext($this->createMock(IL10N::class)); diff --git a/tests/Crypto/CourierMD5RawTest.php b/tests/Crypto/CourierMD5RawTest.php index 5f443a7..d62cdf5 100644 --- a/tests/Crypto/CourierMD5RawTest.php +++ b/tests/Crypto/CourierMD5RawTest.php @@ -53,7 +53,7 @@ class CourierMD5RawTest extends TestCase $this->assertTrue($this->crypto->checkPassword("password", $hash)); } - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->crypto = new CourierMD5Raw($this->createMock(IL10N::class)); diff --git a/tests/Crypto/CourierMD5Test.php b/tests/Crypto/CourierMD5Test.php index 66d3d82..d3a6af9 100644 --- a/tests/Crypto/CourierMD5Test.php +++ b/tests/Crypto/CourierMD5Test.php @@ -53,7 +53,7 @@ class CourierMD5Test extends TestCase $this->assertTrue($this->crypto->checkPassword("password", $hash)); } - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->crypto = new CourierMD5($this->createMock(IL10N::class)); diff --git a/tests/Crypto/CourierSHA1Test.php b/tests/Crypto/CourierSHA1Test.php index b60c3bc..1127cfd 100644 --- a/tests/Crypto/CourierSHA1Test.php +++ b/tests/Crypto/CourierSHA1Test.php @@ -53,7 +53,7 @@ class CourierSHA1Test extends TestCase $this->assertTrue($this->crypto->checkPassword("password", $hash)); } - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->crypto = new CourierSHA1($this->createMock(IL10N::class)); diff --git a/tests/Crypto/CourierSHA256Test.php b/tests/Crypto/CourierSHA256Test.php index 05cebe8..f24bc06 100644 --- a/tests/Crypto/CourierSHA256Test.php +++ b/tests/Crypto/CourierSHA256Test.php @@ -54,7 +54,7 @@ class CourierSHA256Test extends TestCase $this->assertTrue($this->crypto->checkPassword("password", $hash)); } - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->crypto = new CourierSHA256($this->createMock(IL10N::class)); diff --git a/tests/Crypto/CryptArgon2Test.php b/tests/Crypto/CryptArgon2Test.php index 39855fe..c766ef8 100644 --- a/tests/Crypto/CryptArgon2Test.php +++ b/tests/Crypto/CryptArgon2Test.php @@ -54,7 +54,7 @@ class CryptArgon2Test extends TestCase $this->assertTrue($this->crypto->checkPassword("password", $hash)); } - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->crypto = new CryptArgon2($this->createMock(IL10N::class)); diff --git a/tests/Crypto/CryptArgon2idTest.php b/tests/Crypto/CryptArgon2idTest.php new file mode 100644 index 0000000..9bd18ba --- /dev/null +++ b/tests/Crypto/CryptArgon2idTest.php @@ -0,0 +1,62 @@ +<?php +/** + * Nextcloud - user_sql + * + * @copyright 2018 Marcin Łojewski <dev@mlojewski.me> + * @author Marcin Łojewski <dev@mlojewski.me> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +namespace Tests\UserSQL\Crypto; + +use OCA\UserSQL\Crypto\CryptArgon2id; +use OCA\UserSQL\Crypto\IPasswordAlgorithm; +use OCP\IL10N; +use Test\TestCase; + +/** + * Unit tests for class <code>CryptArgon2id</code>. + * + * @author Marcin Łojewski <dev@mlojewski.me> + */ +class CryptArgon2idTest extends TestCase +{ + /** + * @var IPasswordAlgorithm + */ + private $crypto; + + public function testCheckPassword() + { + $this->assertTrue( + $this->crypto->checkPassword( + "password", + "\$argon2id\$v=19\$m=65536,t=4,p=1\$eWhTd3huemlhNGFkWTVSSQ\$BjSh9PINc9df9WU1zppBsYJKvkwUEYHYNUUMTj+QGPw" + ) + ); + } + + public function testPasswordHash() + { + $hash = $this->crypto->getPasswordHash("password"); + $this->assertTrue($this->crypto->checkPassword("password", $hash)); + } + + protected function setUp(): void + { + parent::setUp(); + $this->crypto = new CryptArgon2id($this->createMock(IL10N::class)); + } +} diff --git a/tests/Crypto/CryptBlowfishTest.php b/tests/Crypto/CryptBlowfishTest.php index 1b878fd..6e30ee3 100644 --- a/tests/Crypto/CryptBlowfishTest.php +++ b/tests/Crypto/CryptBlowfishTest.php @@ -54,7 +54,7 @@ class CryptBlowfishTest extends TestCase $this->assertTrue($this->crypto->checkPassword("password", $hash)); } - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->crypto = new CryptBlowfish($this->createMock(IL10N::class)); diff --git a/tests/Crypto/CryptExtendedDESTest.php b/tests/Crypto/CryptExtendedDESTest.php index 5f820b6..9c579a0 100644 --- a/tests/Crypto/CryptExtendedDESTest.php +++ b/tests/Crypto/CryptExtendedDESTest.php @@ -51,7 +51,7 @@ class CryptExtendedDESTest extends TestCase $this->assertTrue($this->crypto->checkPassword("password", $hash)); } - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->crypto = new CryptExtendedDES($this->createMock(IL10N::class)); diff --git a/tests/Crypto/CryptMD5Test.php b/tests/Crypto/CryptMD5Test.php index aadc429..6ea6d24 100644 --- a/tests/Crypto/CryptMD5Test.php +++ b/tests/Crypto/CryptMD5Test.php @@ -53,7 +53,7 @@ class CryptMD5Test extends TestCase $this->assertTrue($this->crypto->checkPassword("password", $hash)); } - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->crypto = new CryptMD5($this->createMock(IL10N::class)); diff --git a/tests/Crypto/CryptSHA256Test.php b/tests/Crypto/CryptSHA256Test.php index b40736d..b648d5b 100644 --- a/tests/Crypto/CryptSHA256Test.php +++ b/tests/Crypto/CryptSHA256Test.php @@ -54,7 +54,7 @@ class CryptSHA256Test extends TestCase $this->assertTrue($this->crypto->checkPassword("password", $hash)); } - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->crypto = new CryptSHA256($this->createMock(IL10N::class)); diff --git a/tests/Crypto/CryptSHA512Test.php b/tests/Crypto/CryptSHA512Test.php index 6ea1035..8acabd9 100644 --- a/tests/Crypto/CryptSHA512Test.php +++ b/tests/Crypto/CryptSHA512Test.php @@ -54,7 +54,7 @@ class CryptSHA512Test extends TestCase $this->assertTrue($this->crypto->checkPassword("password", $hash)); } - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->crypto = new CryptSHA512($this->createMock(IL10N::class)); diff --git a/tests/Crypto/CryptStandardDESTest.php b/tests/Crypto/CryptStandardDESTest.php index b8d8cbf..586bc24 100644 --- a/tests/Crypto/CryptStandardDESTest.php +++ b/tests/Crypto/CryptStandardDESTest.php @@ -51,7 +51,7 @@ class CryptStandardDESTest extends TestCase $this->assertTrue($this->crypto->checkPassword("password", $hash)); } - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->crypto = new CryptStandardDES($this->createMock(IL10N::class)); diff --git a/tests/Crypto/CryptTest.php b/tests/Crypto/CryptTest.php index 680b6cc..7a31078 100644 --- a/tests/Crypto/CryptTest.php +++ b/tests/Crypto/CryptTest.php @@ -54,7 +54,7 @@ class CryptTest extends TestCase $this->assertTrue($this->crypto->checkPassword("password", $hash)); } - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->crypto = new Crypt($this->createMock(IL10N::class)); diff --git a/tests/Crypto/Drupal7Test.php b/tests/Crypto/Drupal7Test.php index 834fcff..6441369 100644 --- a/tests/Crypto/Drupal7Test.php +++ b/tests/Crypto/Drupal7Test.php @@ -53,7 +53,7 @@ class Drupal7Test extends TestCase $this->assertTrue($this->crypto->checkPassword("password", $hash)); } - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->crypto = new Drupal7($this->createMock(IL10N::class)); diff --git a/tests/Crypto/JoomlaTest.php b/tests/Crypto/JoomlaTest.php index 0777c3d..a919db3 100644 --- a/tests/Crypto/JoomlaTest.php +++ b/tests/Crypto/JoomlaTest.php @@ -54,7 +54,7 @@ class JoomlaTest extends TestCase $this->assertTrue($this->crypto->checkPassword("password", $hash)); } - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->crypto = new Joomla($this->createMock(IL10N::class)); diff --git a/tests/Crypto/MD5Test.php b/tests/Crypto/MD5Test.php index d302752..19718d2 100644 --- a/tests/Crypto/MD5Test.php +++ b/tests/Crypto/MD5Test.php @@ -53,7 +53,7 @@ class MD5Test extends TestCase $this->assertTrue($this->crypto->checkPassword("password", $hash)); } - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->crypto = new MD5($this->createMock(IL10N::class)); diff --git a/tests/Crypto/PhpassTest.php b/tests/Crypto/PhpassTest.php index 16e4a0e..cc27038 100644 --- a/tests/Crypto/PhpassTest.php +++ b/tests/Crypto/PhpassTest.php @@ -53,7 +53,7 @@ class PhpassTest extends TestCase $this->assertTrue($this->crypto->checkPassword("password", $hash)); } - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->crypto = new Phpass($this->createMock(IL10N::class)); diff --git a/tests/Crypto/RedmineTest.php b/tests/Crypto/RedmineTest.php index 8dfeee2..072d008 100644 --- a/tests/Crypto/RedmineTest.php +++ b/tests/Crypto/RedmineTest.php @@ -53,7 +53,7 @@ class RedmineTest extends TestCase $this->assertTrue($this->crypto->checkPassword("password", $hash, "salt")); } - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->crypto = new Redmine($this->createMock(IL10N::class)); diff --git a/tests/Crypto/SHA1Test.php b/tests/Crypto/SHA1Test.php index bdee003..bf49358 100644 --- a/tests/Crypto/SHA1Test.php +++ b/tests/Crypto/SHA1Test.php @@ -53,7 +53,7 @@ class SHA1Test extends TestCase $this->assertTrue($this->crypto->checkPassword("password", $hash)); } - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->crypto = new SHA1($this->createMock(IL10N::class)); diff --git a/tests/Crypto/SHA256Test.php b/tests/Crypto/SHA256Test.php index 1c925ab..865083b 100644 --- a/tests/Crypto/SHA256Test.php +++ b/tests/Crypto/SHA256Test.php @@ -53,7 +53,7 @@ class SHA512Test extends TestCase $this->assertTrue($this->crypto->checkPassword("password", $hash)); } - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->crypto = new SHA256($this->createMock(IL10N::class)); diff --git a/tests/Crypto/SHA512Test.php b/tests/Crypto/SHA512Test.php index 791f352..2e23eaa 100644 --- a/tests/Crypto/SHA512Test.php +++ b/tests/Crypto/SHA512Test.php @@ -54,7 +54,7 @@ class SHA512Test extends TestCase $this->assertTrue($this->crypto->checkPassword("password", $hash)); } - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->crypto = new SHA512($this->createMock(IL10N::class)); diff --git a/tests/Crypto/SHA512WhirlpoolTest.php b/tests/Crypto/SHA512WhirlpoolTest.php index 3239776..1885582 100644 --- a/tests/Crypto/SHA512WhirlpoolTest.php +++ b/tests/Crypto/SHA512WhirlpoolTest.php @@ -54,7 +54,7 @@ class SHA512WhirlpoolTest extends TestCase $this->assertTrue($this->crypto->checkPassword("password", $hash)); } - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->crypto = new SHA512Whirlpool($this->createMock(IL10N::class)); diff --git a/tests/Crypto/SSHA256Test.php b/tests/Crypto/SSHA256Test.php index e3189d0..2fbc0db 100644 --- a/tests/Crypto/SSHA256Test.php +++ b/tests/Crypto/SSHA256Test.php @@ -54,7 +54,7 @@ class SSHA256Test extends TestCase $this->assertTrue($this->crypto->checkPassword("password", $hash)); } - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->crypto = new SSHA256($this->createMock(IL10N::class)); diff --git a/tests/Crypto/SSHA512Test.php b/tests/Crypto/SSHA512Test.php index b6b5f72..dcbbd6f 100644 --- a/tests/Crypto/SSHA512Test.php +++ b/tests/Crypto/SSHA512Test.php @@ -54,7 +54,7 @@ class SSHA512Test extends TestCase $this->assertTrue($this->crypto->checkPassword("password", $hash)); } - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->crypto = new SSHA512($this->createMock(IL10N::class)); diff --git a/tests/Crypto/WCF2Test.php b/tests/Crypto/WCF2Test.php index 91faa91..fde0a71 100644 --- a/tests/Crypto/WCF2Test.php +++ b/tests/Crypto/WCF2Test.php @@ -54,7 +54,7 @@ class WCF2Test extends TestCase $this->assertTrue($this->crypto->checkPassword("password", $hash)); } - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->crypto = new WCF2($this->createMock(IL10N::class)); diff --git a/tests/Crypto/WhirlpoolTest.php b/tests/Crypto/WhirlpoolTest.php index ff92af0..5b0de64 100644 --- a/tests/Crypto/WhirlpoolTest.php +++ b/tests/Crypto/WhirlpoolTest.php @@ -54,7 +54,7 @@ class WhirlpoolTest extends TestCase $this->assertTrue($this->crypto->checkPassword("password", $hash)); } - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->crypto = new Whirlpool($this->createMock(IL10N::class)); |