Completed
Push — master ( 5b2039...ff2518 )
by Marcel
06:16
created

Signer::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
ccs 5
cts 5
cp 1
rs 9.4285
cc 1
eloc 4
nc 1
nop 1
crap 1
1
<?php
2
3
namespace UMA\Psr7Hmac;
4
5
use Psr\Http\Message\MessageInterface;
6
use Psr\Http\Message\RequestInterface;
7
use UMA\Psr7Hmac\Internal\HashCalculator;
8
use UMA\Psr7Hmac\Internal\MessageSerializer;
9
use UMA\Psr7Hmac\Internal\NonceProvider;
10
11
class Signer
12
{
13
    /**
14
     * @var string
15
     */
16
    private $secret;
17
18
    /**
19
     * @var HashCalculator
20
     */
21
    private $calculator;
22
23
    /**
24
     * @var NonceProvider
25
     */
26
    private $nonceProvider;
27
28
    /**
29
     * @param string $secret
30
     */
31 98
    public function __construct($secret)
32
    {
33 98
        $this->secret = $secret;
34 98
        $this->calculator = new HashCalculator();
35 98
        $this->nonceProvider = new NonceProvider();
36 98
    }
37
38
    /**
39
     * @param MessageInterface $message
40
     *
41
     * @return MessageInterface The signed message.
42
     *
43
     * @throws \InvalidArgumentException When $message is an implementation of
44
     *                                   MessageInterface that cannot be
45
     *                                   serialized and thus neither signed.
46
     */
47 98
    public function sign(MessageInterface $message)
48
    {
49 98
        $serialization = MessageSerializer::serialize(
50 98
            $preSignedMessage = $this->withSignedHeadersHeader(
51 98
                $message->withHeader(Specification::NONCE_HEADER, $this->nonceProvider->randomNonce())
52 98
            )
53 98
        );
54
55 98
        return $preSignedMessage->withHeader(
56 98
            Specification::AUTH_HEADER,
57 98
            Specification::AUTH_PREFIX.$this->calculator->hmac($serialization, $this->secret)
58 98
        );
59
    }
60
61
    /**
62
     * @param MessageInterface $message
63
     *
64
     * @return MessageInterface
65
     */
66 98
    private function withSignedHeadersHeader(MessageInterface $message)
67
    {
68 98
        $headers = array_keys(array_change_key_case($message->getHeaders(), CASE_LOWER));
69 98
        array_push($headers, mb_strtolower(Specification::SIGN_HEADER));
70
71
        // Some of the tested RequestInterface implementations do not include
72
        // the Host header in $message->getHeaders(), so it is explicitly set when needed
73 98
        if ($message instanceof RequestInterface && !in_array('host', $headers)) {
74 20
            array_push($headers, 'host');
75 20
        }
76
77
        // There is no guarantee about the order of the headers returned by
78
        // $message->getHeaders(), so they are explicitly sorted in order
79
        // to produce the exact same string regardless of the underlying implementation
80 98
        sort($headers);
81
82 98
        return $message->withHeader(Specification::SIGN_HEADER, implode(',', $headers));
83
    }
84
}
85