Rev 1099 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1099 | Rev 1116 | ||
---|---|---|---|
Line 23... | Line 23... | ||
23 | \defined('INSIDE_OIDPLUS') or die; |
23 | \defined('INSIDE_OIDPLUS') or die; |
24 | // phpcs:enable PSR1.Files.SideEffects |
24 | // phpcs:enable PSR1.Files.SideEffects |
25 | 25 | ||
26 | class OIDplusAuthPluginBCrypt extends OIDplusAuthPlugin { |
26 | class OIDplusAuthPluginBCrypt extends OIDplusAuthPlugin { |
27 | 27 | ||
- | 28 | /** |
|
- | 29 | * @param bool $html |
|
- | 30 | * @return void |
|
- | 31 | * @throws OIDplusException |
|
- | 32 | */ |
|
28 | public function init($html=true) { |
33 | public function init(bool $html=true) { |
29 | // Note: Example #3 here https://www.php.net/manual/en/function.password-hash.php can help you with finding a good cost value |
34 | // Note: Example #3 here https://www.php.net/manual/en/function.password-hash.php can help you with finding a good cost value |
30 | OIDplus::config()->prepareConfigKey('ra_bcrypt_cost', 'How complex should the BCrypt hash of RA passwords be? (Only for plugin A3_bcrypt; values 4-31, default 10)', 10, OIDplusConfig::PROTECTION_EDITABLE, function($value) { |
35 | OIDplus::config()->prepareConfigKey('ra_bcrypt_cost', 'How complex should the BCrypt hash of RA passwords be? (Only for plugin A3_bcrypt; values 4-31, default 10)', '10', OIDplusConfig::PROTECTION_EDITABLE, function($value) { |
31 | if (empty($value) || !is_int($value) || ($value<4) || ($value>31)) { |
36 | if (empty($value) || !is_numeric($value) || ($value<4) || ($value>31)) { |
32 | throw new OIDplusException(_L('Invalid value for "cost" (must be 4-31, default 10).')); |
37 | throw new OIDplusException(_L('Invalid value for "cost" (must be 4-31, default 10).')); |
33 | } |
38 | } |
34 | }); |
39 | }); |
35 | } |
40 | } |
36 | 41 | ||
- | 42 | /** |
|
- | 43 | * @param string $authKey |
|
- | 44 | * @return bool |
|
- | 45 | */ |
|
37 | private function supportedCryptAlgo($authKey) { |
46 | private function supportedCryptAlgo(string $authKey): bool { |
38 | return str_starts_with($authKey, '$2$') || |
47 | return str_starts_with($authKey, '$2$') || |
39 | str_starts_with($authKey, '$2a$') || |
48 | str_starts_with($authKey, '$2a$') || |
40 | str_starts_with($authKey, '$2b$') || |
49 | str_starts_with($authKey, '$2b$') || |
41 | str_starts_with($authKey, '$2x$') || |
50 | str_starts_with($authKey, '$2x$') || |
42 | str_starts_with($authKey, '$2y$'); |
51 | str_starts_with($authKey, '$2y$'); |
43 | } |
52 | } |
44 | 53 | ||
- | 54 | /** |
|
- | 55 | * @param OIDplusRAAuthInfo $authInfo |
|
- | 56 | * @param string $check_password |
|
- | 57 | * @return bool |
|
- | 58 | */ |
|
45 | public function verify(OIDplusRAAuthInfo $authInfo, $check_password) { |
59 | public function verify(OIDplusRAAuthInfo $authInfo, string $check_password): bool { |
46 | $authKey = $authInfo->getAuthKey(); |
60 | $authKey = $authInfo->getAuthKey(); |
47 | 61 | ||
48 | if (!$this->supportedCryptAlgo($authKey)) { |
62 | if (!$this->supportedCryptAlgo($authKey)) { |
49 | // Unsupported algorithm |
63 | // Unsupported algorithm |
50 | return false; |
64 | return false; |
Line 55... | Line 69... | ||
55 | // Alg Cost Salt (128 bit) Hash |
69 | // Alg Cost Salt (128 bit) Hash |
56 | 70 | ||
57 | return password_verify($check_password, $authKey); |
71 | return password_verify($check_password, $authKey); |
58 | } |
72 | } |
59 | 73 | ||
- | 74 | /** |
|
- | 75 | * @param string $password |
|
- | 76 | * @return OIDplusRAAuthInfo |
|
- | 77 | * @throws OIDplusException |
|
- | 78 | */ |
|
60 | public function generate($password): OIDplusRAAuthInfo { |
79 | public function generate(string $password): OIDplusRAAuthInfo { |
61 | if (strlen($password) > 72) throw new OIDplusException(_L('Password is too long (max %1 bytes)',72)); |
80 | if (strlen($password) > 72) throw new OIDplusException(_L('Password is too long (max %1 bytes)',72)); |
62 | $cost = OIDplus::config()->getValue('ra_bcrypt_cost', 10); |
81 | $cost = OIDplus::config()->getValue('ra_bcrypt_cost', 10); |
63 | $calc_authkey = password_hash($password, PASSWORD_BCRYPT, array("cost" => $cost)); |
82 | $calc_authkey = password_hash($password, PASSWORD_BCRYPT, array("cost" => $cost)); |
64 | if (!$calc_authkey) throw new OIDplusException(_L('Error creating password hash')); |
83 | if (!$calc_authkey) throw new OIDplusException(_L('Error creating password hash')); |
65 | assert($this->supportedCryptAlgo($calc_authkey)); |
84 | assert($this->supportedCryptAlgo($calc_authkey)); |
66 | return new OIDplusRAAuthInfo($calc_authkey); |
85 | return new OIDplusRAAuthInfo($calc_authkey); |
67 | } |
86 | } |
68 | 87 | ||
- | 88 | /** |
|
- | 89 | * @param string $reason |
|
- | 90 | * @return bool |
|
- | 91 | */ |
|
69 | public function availableForHash(&$reason): bool { |
92 | public function availableForHash(string &$reason): bool { |
70 | if (version_compare(PHP_VERSION, '7.4.0') >= 0) { |
93 | if (version_compare(PHP_VERSION, '7.4.0') >= 0) { |
71 | $ok = in_array('2', password_algos()) || |
94 | $ok = in_array('2', password_algos()) || |
72 | in_array('2a', password_algos()) || |
95 | in_array('2a', password_algos()) || |
73 | in_array('2b', password_algos()) || |
96 | in_array('2b', password_algos()) || |
74 | in_array('2x', password_algos()) || |
97 | in_array('2x', password_algos()) || |
Line 82... | Line 105... | ||
82 | 105 | ||
83 | $reason = _L('No fitting hash algorithm found'); |
106 | $reason = _L('No fitting hash algorithm found'); |
84 | return false; |
107 | return false; |
85 | } |
108 | } |
86 | 109 | ||
- | 110 | /** |
|
- | 111 | * @param string $reason |
|
- | 112 | * @return bool |
|
- | 113 | */ |
|
87 | public function availableForVerify(&$reason): bool { |
114 | public function availableForVerify(string &$reason): bool { |
88 | return $this->availableForHash($reason); |
115 | return $this->availableForHash($reason); |
89 | } |
116 | } |
90 | 117 | ||
91 | } |
118 | } |