Completed
Push — develop ( 054456...c0e59c )
by Marek
04:15
created

SaltedShaPasswordEncoder::demergePasswordAndSalt()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 7
nc 2
nop 1
1
<?php
2
namespace AppBundle\Security\Encoder;
3
4
use Symfony\Component\Security\Core\Encoder\BasePasswordEncoder;
5
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
6
7
class SaltedShaPasswordEncoder extends BasePasswordEncoder
8
{
9
    const PART_LENGTH = 20;
10
    const SALT_LENGTH = 40;
11
12
    //region PasswordEncoderInterface
13
14
    /**
15
     * Encodes the raw password.
16
     *
17
     * @param string $raw The password to encode
18
     * @param string $salt The salt
19
     *
20
     * @return string The encoded password
21
     */
22
    public function encodePassword($raw, $salt)
23
    {
24
        if ($this->isPasswordTooLong($raw)) {
25
            throw new BadCredentialsException('Invalid password');
26
        }
27
28
        $salt = $this->ensureSaltLength($salt);
29
30
        $hash = sha1($salt.md5($raw));
31
32
        return $this->mergePasswordAndSalt($hash, $salt);
33
    }
34
35
    /**
36
     * Checks a raw password against an encoded password.
37
     *
38
     * @param string $encoded An encoded password
39
     * @param string $raw A raw password
40
     * @param string $salt The salt
41
     *
42
     * @return bool true if the password is valid, false otherwise
43
     */
44
    public function isPasswordValid($encoded, $raw, $salt)
45
    {
46
        $salt = $this->demergePasswordAndSalt($encoded);
47
48
        return !$this->isPasswordTooLong($raw) && $this->comparePasswords($encoded, $this->encodePassword($raw, $salt));
0 ignored issues
show
Documentation introduced by
$salt is of type array<integer,string,{"0":"string","1":"string"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
49
    }
50
51
    //endregion
52
53
    /**
54
     * @inheritdoc
55
     *
56
     * @param string $mergedPasswordSalt
57
     *
58
     * @return array Array consisting of password hash and salt
59
     */
60
    protected function demergePasswordAndSalt($mergedPasswordSalt)
61
    {
62
        if (empty($mergedPasswordSalt)) {
63
            return ['', ''];
64
        }
65
66
        $hashParts = str_split($mergedPasswordSalt, self::PART_LENGTH);
67
        $salt = $hashParts[0].$hashParts[3];
68
        $password = $hashParts[1].$hashParts[2];
69
70
        return [$password, $salt];
71
    }
72
73
    /**
74
     * @inheritdoc
75
     *
76
     * @param string $password
77
     * @param string $salt
78
     *
79
     * @return string
80
     */
81
    protected function mergePasswordAndSalt($password, $salt)
82
    {
83
        $saltParts = str_split($salt, self::PART_LENGTH);
84
85
        return sprintf('%s%s%s', $saltParts[0], $password, $saltParts[1]);
86
    }
87
88
    private function ensureSaltLength($salt)
89
    {
90
        if (strlen($salt) === self::SALT_LENGTH) {
91
            return $salt;
92
        }
93
94
        while (strlen($salt) < self::SALT_LENGTH) {
95
            $salt .= uniqid('', true);
96
        }
97
98
        return substr($salt, 0, self::SALT_LENGTH);
99
    }
100
}
101