HashHmac::create()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 3
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 12
    public function __construct($privateKey, $algo = 'sha512', $timezone = 'UTC')
48
    {
49 12
        $this->privateKey = $privateKey;
50 12
        $this->algorithm = $algo;
51 12
        $this->timezone = new \DateTimeZone($timezone);
52 12
    }
53
54
55
    /**
56
     * Create Hash Hmac from payload.
57
     *
58
     * @param array $payload
59
     * @return string
60
     */
61 6
    public function create(array $payload = []){
62 6
        $hash = $this->generate($this->algorithm, $payload, $this->privateKey);
63 6
        return base64_encode($this->algorithm.'='.$hash);
64
    }
65
66
    /**
67
     * Internal Function to creates hash from payload.
68
     *
69
     * @param  array $payload
70
     * @return mixed
71
     */
72 7
    private function generate($algorithm, array $payload = [], $privateKey)
73
    {
74 7
        $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 7
        return hash_hmac(
77
            $algorithm,
78 7
            $this->payload,
79
            $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 6
    public function verify($encodedHash, array $payload = [])
92
    {
93 6
        $decodedHash = base64_decode($encodedHash);
94
95 6
        list($algo, $hash) = array_pad( explode('=', $decodedHash), 4, $this->algorithm);
96
97 6
        $payloadHash = $this->generate($this->algorithm, $payload, $this->privateKey);
98
99
        try {
100 6
            $this->verifyAlgorithm($algo);
101 5
            $this->verifyHash($hash, $payloadHash);
102 4
        } catch (\Exception $e) {
103 4
            throw new \Exception($e->getMessage());
104
        }
105
106 2
        return true;
107
108
    }
109
110
    /**
111
     * With Private Key.
112
     *
113
     * @param string $key
114
     * @return $this
115
     */
116 2
    public function withPrivateKey(string $key)
117
    {
118 2
        $new = clone $this;
119 2
        $new->privateKey = $key;
120 2
        return $new;
121
    }
122
123
    /**
124
     * With Payload Data
125
     *
126
     * @param array $payload
127
     * @return $this
128
     */
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 1
    public function getAlgorithm()
142
    {
143 1
        return $this->algorithm;
144
    }
145
146
147
    /**
148
     * Return active payload.
149
     *
150
     * @return array
151
     */
152
    public function getPayload(){
153
        return $this->payload;
154
    }
155
156
    /**
157
     * Returns Private Key
158
     *
159
     * @return string
160
     */
161 2
    public function getPrivateKey()
162
    {
163 2
        return $this->privateKey;
164
    }
165
166
    /**
167
     * @param string $hash
168
     * @param string $payloadHash
169
     * @return bool
170
     * @throws \Exception
171
     */
172 5
    private function verifyHash($hash = '', $payloadHash = '')
173
    {
174 5
        if (!is_string($hash) || !is_string($payloadHash)) {
175
            throw new \Exception('hashes are not of the same type');
176
        }
177
178 5
        if (\md5($hash) === \md5($payloadHash)
179 5
            && strlen($hash) === strlen($payloadHash)
180 5
            && hash_equals($hash, $payloadHash)
181
        ) {
182 2
            return true;
183
        }
184
185 3
        throw new \Exception('hashes do not match');
186
    }
187
188
    /**
189
     * @param $algo
190
     * @return string
191
     * @throws \Exception
192
     */
193 8
    private function verifyAlgorithm($algo)
194
    {
195
196 8
        foreach (hash_algos() as $validAlgo) {
197 8
            if ($algo === $validAlgo) {
198 6
                $this->algorithm = $validAlgo;
199 8
                return $this->algorithm;
200
            }
201
        }
202 2
        throw new \Exception('Algorithm is not valid');
203
    }
204
}
205