Completed
Push — master ( 48f773...027340 )
by
unknown
08:02
created

SignatureParameterHandler::verifyParameterBag()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 16
ccs 8
cts 8
cp 1
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 8
nc 3
nop 2
crap 3
1
<?php
2
3
namespace MediaMonks\SonataMediaBundle\Handler;
4
5
use MediaMonks\SonataMediaBundle\Exception\SignatureInvalidException;
6
use MediaMonks\SonataMediaBundle\Model\MediaInterface;
7
use MediaMonks\SonataMediaBundle\ParameterBag\ParameterBagInterface;
8
use Mockery\Generator\Parameter;
9
10
class SignatureParameterHandler implements ParameterHandlerInterface
11
{
12
    const PARAMETER_SIGNATURE = 's';
13
    const PARAMETER_BUST_CACHE = 'bc';
14
15
    /**
16
     * @var string
17
     */
18
    private $key;
19
20
    /**
21
     * @var string
22
     */
23
    private $hashAlgorithm;
24
25
    /**
26
     * @param string $key
27
     * @param string $hashAlgorithm
28
     */
29 15
    public function __construct($key, $hashAlgorithm = 'sha256')
30
    {
31 15
        $this->key = $key;
32 15
        $this->hashAlgorithm = $hashAlgorithm;
33 15
    }
34
35
    /**
36
     * @param MediaInterface $media
37
     * @param ParameterBagInterface $parameterBag
38
     * @return array
39
     */
40 8
    public function getRouteParameters(MediaInterface $media, ParameterBagInterface $parameterBag)
41
    {
42 8
        $parameters = $parameterBag->toArray($media);
43 8
        $parameters[self::PARAMETER_SIGNATURE] = $this->calculateSignature($parameters);
44
45 8
        return $parameters;
46
    }
47
48
    /**
49
     * @param MediaInterface $media
50
     * @param ParameterBagInterface $parameterBag
51
     * @return ImageParameterBag|ParameterBagInterface
52
     * @throws SignatureInvalidException
53
     */
54 9
    public function validateParameterBag(MediaInterface $media, ParameterBagInterface $parameterBag)
55
    {
56 9
        $data = $parameterBag->toArray($media);
57
58 9
        if (!isset($data[self::PARAMETER_SIGNATURE])) {
59 1
            throw new SignatureInvalidException();
60
        }
61
62 8
        $signature = $data[self::PARAMETER_SIGNATURE];
63 8
        $parameterBag->removeExtra(self::PARAMETER_SIGNATURE);
64
65 8
        if (!$this->isValid($media, $parameterBag, $signature)) {
66 1
            throw new SignatureInvalidException();
67
        }
68
69 7
        return $parameterBag;
70
    }
71
72
    /**
73
     * @param MediaInterface $media
74
     * @param ParameterBagInterface $parameterBag
75
     * @param $expectedSignature
76
     * @return bool
77
     */
78 8
    private function isValid(MediaInterface $media, ParameterBagInterface $parameterBag, $expectedSignature)
79
    {
80 8
        return hash_equals($this->calculateSignature($parameterBag->toArray($media)), $expectedSignature);
81
    }
82
83
    /**
84
     * @param array $parameters
85
     * @return string
86
     */
87 11
    private function calculateSignature(array $parameters)
88
    {
89 11
        return hash_hmac($this->hashAlgorithm, $this->key, json_encode($this->normalize($parameters)));
90
    }
91
92
    /**
93
     * @param array $parameters
94
     * @return array
95
     */
96 11
    private function normalize(array $parameters)
97
    {
98 11
        if (isset($parameters[self::PARAMETER_BUST_CACHE])) {
99 7
            unset($parameters[self::PARAMETER_BUST_CACHE]);
100
        }
101 11
        ksort($parameters);
102
103 11
        return array_map('strval', $parameters);
104
    }
105
}
106