ILIAS  trunk Revision v11.0_alpha-2638-g80c1d007f79
class.ilBcryptPhpPasswordEncoder.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
27 {
28  private const string COST = 'cost';
29 
30  private string $costs = '08';
31 
36  public function __construct(array $config = [])
37  {
38  foreach ($config as $key => $value) {
39  if (strtolower($key) === self::COST) {
40  $this->setCosts($value);
41  }
42  }
43 
44  if (!isset($config[self::COST]) && static::class === self::class) {
45  // Determine the costs only if they are not passed in constructor
46  $this->setCosts((string) $this->benchmarkCost());
47  }
48  }
49 
54  public function benchmarkCost(float $time_target = 0.05): int
55  {
56  $cost = 8;
57 
58  do {
59  ++$cost;
60  $start = microtime(true);
61  $encoder = new self([self::COST => (string) $cost]);
62  $encoder->encodePassword('test', '');
63  $end = microtime(true);
64  } while (($end - $start) < $time_target && $cost < 32);
65 
66  return $cost;
67  }
68 
69  public function getName(): string
70  {
71  return 'bcryptphp';
72  }
73 
74  public function getCosts(): string
75  {
76  return $this->costs;
77  }
78 
79  public function setCosts(string $costs): void
80  {
81  if ($costs !== '') {
82  $numeric_costs = (int) $costs;
83  if ($numeric_costs < 4 || $numeric_costs > 31) {
84  throw new ilPasswordException('The costs parameter of bcrypt must be in range 04-31');
85  }
86  $this->costs = sprintf('%1$02d', $numeric_costs);
87  }
88  }
89 
90  public function encodePassword(string $raw, string $salt): string
91  {
92  if ($this->isPasswordTooLong($raw)) {
93  throw new ilPasswordException('Invalid password.');
94  }
95 
96  return password_hash($raw, PASSWORD_BCRYPT, [
97  self::COST => $this->costs
98  ]);
99  }
100 
101  public function isPasswordValid(string $encoded, string $raw, string $salt): bool
102  {
103  return password_verify($raw, $encoded);
104  }
105 
106  public function requiresReencoding(string $encoded): bool
107  {
108  return password_needs_rehash($encoded, PASSWORD_BCRYPT, [
109  self::COST => $this->costs
110  ]);
111  }
112 }
getName()
Returns a unique name/id of the concrete password encoder.
encodePassword(string $raw, string $salt)
Encodes the raw password.
requiresReencoding(string $encoded)
Returns whether the encoded password needs to be re-encoded.
isPasswordValid(string $encoded, string $raw, string $salt)
Checks a raw password against an encoded password.