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
diff --git a/README.md b/README.md
index 5027504..3b17dd1 100644
--- a/README.md
+++ b/README.md
@@ -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 @@
auth
-
+
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 @@
+
+ * @author Marcin Łojewski
+ *
+ * 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 .
+ */
+
+namespace OCA\UserSQL\Crypto;
+
+use OCP\IL10N;
+
+/**
+ * Argon2id Crypt hash implementation.
+ *
+ * @see crypt()
+ * @author Marcin Łojewski
+ */
+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 @@
+
+ * @author Marcin Łojewski
+ *
+ * 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 .
+ */
+
+namespace Tests\UserSQL\Crypto;
+
+use OCA\UserSQL\Crypto\CryptArgon2id;
+use OCA\UserSQL\Crypto\IPasswordAlgorithm;
+use OCP\IL10N;
+use Test\TestCase;
+
+/**
+ * Unit tests for class CryptArgon2id.
+ *
+ * @author Marcin Łojewski
+ */
+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));