Test Failed
Push — master ( 7e5dab...fc366b )
by Dan
06:52
created

HashHmac::withPrivateKey()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Ds\Authenticate;
4
5
/**
6
 * Hmac hashing functions.
7
 *
8
 * @package Ds\Authenticate
9
 * @author  Dan Smith <[email protected]>
10
 */
11
class HashHmac
12
{
13
14
    /**
15
     * Hashing Algorithm.
16
     *
17
     * @var string
18
     */
19
    private $algorithm;
20
21
    /**
22
     * Private Key.
23
     *
24
     * @var string
25
     */
26
    private $privateKey;
27
28
    /**
29
     * Payload Data.
30
     *
31
     * @var array
32
     */
33
    private $payload = [];
34
35
    /**
36
     * Date Time Zone.
37
     *
38
     * @var \DateTimeZone
39
     */
40
    private $timezone;
41
42
    /**
43
     * @param string $privateKey
44
     * @param string $algo
45
     * @param string $timezone
46
     */
47
    public function __construct($privateKey, $algo = 'sha512', $timezone = 'UTC')
48
    {
49
        $this->privateKey = $privateKey;
50
        $this->algorithm = $algo;
51
        $this->timezone = new \DateTimeZone($timezone);
52
    }
53 13
54
55 13
    /**
56 13
     * Create Hash Hmac from payload.
57 13
     *
58 13
     * @param array $payload
59
     * @return string
60
     */
61
    public function create(array $payload = []){
62
        $hash = $this->generate($this->algorithm, $payload, $this->privateKey);
63
        return base64_encode($this->algorithm.'='.$hash);
64
    }
65 4
66
    /**
67
     * Internal Function to creates hash from payload.
68 4
     *
69
     * @param  array $payload
70 4
     * @return mixed
71 4
     */
72 4
    private function generate($algorithm, array $payload = [], $privateKey)
73
    {
74 4
        $this->payload = json_encode($payload);
0 ignored issues
show
Documentation Bug introduced by
It seems like json_encode($payload) of type string is incompatible with the declared type array of property $payload.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
75
76
        return hash_hmac(
77 2
            $algorithm,
78 2
            $this->payload,
79 2
            $privateKey
80
        );
81
    }
82
83
    /**
84
     * Compare received hash against payload.
85
     *
86
     * @param  $encodedHash
87
     * @param  array       $payload
88
     * @return bool
89
     * @throws \Exception
90
     */
91 3
    public function verify($encodedHash, array $payload = [])
92
    {
93 3
        $decodedHash = base64_decode($encodedHash);
94
95 3
        list($algo, $hash) = array_pad( explode('=', $decodedHash), 4, $this->algorithm);
96 3
97
        $payloadHash = $this->generate($this->algorithm, $payload, $this->privateKey);
98
99 3
        try {
100 2
            $this->verifyAlgorithm($algo);
101 3
            $this->verifyHash($hash, $payloadHash);
102 2
        } catch (\Exception $e) {
103
            throw new \Exception($e->getMessage());
104
        }
105 1
106
        return true;
107
108
    }
109
110
    /**
111
     * With Private Key.
112
     *
113
     * @param string $key
114 1
     * @return $this
115
     */
116 1
    public function withPrivateKey(string $key)
117 1
    {
118 1
        $new = clone $this;
119
        $new->privateKey = $key;
120
        return $new;
121
    }
122
123
    /**
124
     * With Payload Data
125
     *
126 1
     * @param array $payload
127
     * @return $this
128 1
     */
129
    public function withPayload(array $payload)
130
    {
131
        $new = clone $this;
132
        $new->payload = $payload;
133
        return $new;
134
    }
135
136
    /**
137
     * Return current Algorithm
138
     *
139
     * @return string
140
     */
141 2
    public function getAlgorithm()
142
    {
143 2
        return $this->algorithm;
144
    }
145
146
147
    /**
148
     * Return active payload.
149
     *
150
     * @return array
151
     */
152 7
    public function getPayload(){
153
        return $this->payload;
154 7
    }
155 1
156
    /**
157 6
     * Returns Private Key
158 6
     *
159 6
     * @return string
160 3
     */
161
    public function getPrivateKey()
162 3
    {
163
        return $this->privateKey;
164
    }
165 5
166
    /**
167 5
     * @param string $hash
168 5
     * @param string $payloadHash
169 3
     * @return bool
170 3
     * @throws \Exception
171
     */
172 5
    private function verifyHash($hash = '', $payloadHash = '')
173 2
    {
174
        if (!is_string($hash) || !is_string($payloadHash)) {
175
            throw new \Exception('hashes are not of the same type');
176
        }
177
178
        if (\md5($hash) === \md5($payloadHash)
179
            && strlen($hash) === strlen($payloadHash)
180
            && hash_equals($hash, $payloadHash)
181
        ) {
182
            return true;
183
        }
184
185
        throw new \Exception('hashes do not match');
186
    }
187
188
    /**
189
     * @param $algo
190
     * @return string
191
     * @throws \Exception
192
     */
193
    private function verifyAlgorithm($algo)
194
    {
195
196
        foreach (hash_algos() as $validAlgo) {
197
            if ($algo === $validAlgo) {
198
                $this->algorithm = $validAlgo;
199
                return $this->algorithm;
200
            }
201
        }
202
        throw new \Exception('Algorithm is not valid');
203
    }
204
}
205