Issues (2)

src/Password.php (2 issues)

Labels
Severity
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * Copyright (c) Andreas Heigl<[email protected]> All rights reserved.
7
 *
8
 * Licensed under the MIT License. See LICENSE.md file in the
9
 * project root for full license information.
10
 */
11
12
namespace Org_Heigl\Password;
13
14
use function define;
15
use function defined;
16
use function password_hash;
17
use function password_needs_rehash;
18
use function version_compare;
19
use const PASSWORD_DEFAULT;
20
use const PHP_VERSION;
21
22
final class Password
23
{
24
    private $password;
25
26
    private $hash;
27
28
    private function __construct(string $password)
29
    {
30
        $this->hash = null;
31
        $this->password = sodium_crypto_secretbox(
32
            $password,
33
            ORG_HEIGL_PASSWORD_PASSWORD_NONCE,
34
            ORG_HEIGL_PASSWORD_PASSWORD_KEY
35
        );
36
    }
37
38
    public static function createFromPlainText(string $password) : self
39
    {
40
        return new self($password);
41
    }
42
43
    public function __toString()
44
    {
45
        return '********';
46
    }
47
48
    public function __debugInfo()
49
    {
50
        return [
51
            'password' => '********'
52
        ];
53
    }
54
55
    public function matchesHash(string $hash) : bool
56
    {
57
        $this->hash = $hash;
58
59
        return password_verify(
60
            $this->getPasswordInPlainText(),
61
            $this->hash
62
        );
63
    }
64
65
    /**
66
     * @deprecated Use Password::needsRehash() instead
67
     */
68
    public function shouldBeRehashed($algorithm = PASSWORD_DEFAULT, array $options = []) : bool
69
    {
70
        if (null === $this->hash) {
71
            return true;
72
        }
73
74
        return password_needs_rehash($this->hash, $algorithm, $options);
75
    }
76
77
    public function needsRehash(string $algorithm = PASSWORD_DEFAULT, array $options = []): bool
78
    {
79
        if (null === $this->hash) {
80
            return true;
81
        }
82
        if (0 < version_compare(PHP_VERSION, '7.4.0')) {
83
            $algorithm = (int) $algorithm;
84
        }
85
        return password_needs_rehash($this->hash, $algorithm, $options);
0 ignored issues
show
It seems like $algorithm can also be of type string; however, parameter $algo of password_needs_rehash() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

85
        return password_needs_rehash($this->hash, /** @scrutinizer ignore-type */ $algorithm, $options);
Loading history...
86
    }
87
88
    /**
89
     * @deprecated Use Password::hash() instead
90
     */
91
    public function getNewHash($algorithm = PASSWORD_DEFAULT, array $options = []) : string
92
    {
93
        return password_hash($this->getPasswordInPlainText(), $algorithm, $options);
94
    }
95
96
    public function hash(string $algorithm = PASSWORD_DEFAULT, array $options = []): string
97
    {
98
        if (0 < version_compare(PHP_VERSION, '7.4.0')) {
99
            $algorithm = (int) $algorithm;
100
        }
101
        return password_hash($this->getPasswordInPlainText(), $algorithm, $options);
0 ignored issues
show
It seems like $algorithm can also be of type string; however, parameter $algo of password_hash() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

101
        return password_hash($this->getPasswordInPlainText(), /** @scrutinizer ignore-type */ $algorithm, $options);
Loading history...
102
    }
103
104
    public function getPlainTextPasswordAndYesIKnowWhatIAmDoingHere() : string
105
    {
106
        trigger_error(
107
            'Password was leaked in clear text using the ' .
108
            '"Password::getPlainTextPasswordAndYesIKnowWhatIAmDoingHere"-function!!',
109
            E_USER_WARNING
110
        );
111
112
        return $this->getPasswordInPlainText();
113
    }
114
115
    private function getPasswordInPlainText() : string
116
    {
117
        return sodium_crypto_secretbox_open(
118
            $this->password,
119
            ORG_HEIGL_PASSWORD_PASSWORD_NONCE,
120
            ORG_HEIGL_PASSWORD_PASSWORD_KEY
121
        );
122
    }
123
124
    /**
125
     * @throws \Org_Heigl\Password\PasswordException
126
     */
127
    public function __wakeup() : void
128
    {
129
        throw PasswordException::getWakeupException();
130
    }
131
132
    /**
133
     * @throws \Org_Heigl\Password\PasswordException
134
     */
135
    public function __sleep() : array
136
    {
137
        throw PasswordException::getSleepException();
138
    }
139
140
    /**
141
     * @throws \Org_Heigl\Password\PasswordException
142
     */
143
    public function __clone()
144
    {
145
        throw PasswordException::getCloneException();
146
    }
147
}
148
149
define('ORG_HEIGL_PASSWORD_PASSWORD_NONCE', random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES));
150
define('ORG_HEIGL_PASSWORD_PASSWORD_KEY', sodium_crypto_secretbox_keygen());
151