Signature   A
last analyzed

Complexity

Total Complexity 6

Size/Duplication

Total Lines 67
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 6
eloc 16
c 1
b 0
f 0
dl 0
loc 67
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A derive() 0 15 1
A getSignatureHash() 0 8 2
A serializePayload() 0 14 3
1
<?php declare(strict_types=1);
2
3
namespace ncryptf;
4
5
use DateTime;
6
7
final class Signature
8
{
9
    /**
10
     * Constructs a new signature
11
     *
12
     * @param string       $httpMethod The HTTP method
13
     * @param string       $uri        The full URI with query string parameters
14
     * @param string       $salt       32 byte salt
15
     * @param DateTime     $date       The datetime object
16
     * @param array|string $payload    An array containing the data to sign
17
     * @param int          $version    The signature version to generate
18
     */
19
    public static function derive(
20
        string $httpMethod,
21
        string $uri,
22
        string $salt,
23
        DateTime $date,
24
        $payload = '',
25
        int $version = 2
26
    ) : string {
27
        $httpMethod = \strtoupper($httpMethod);
28
        $data = self::serializePayload($payload);
29
        $hash = self::getSignatureHash($data, $salt, $version);
30
        $time = $date->format(\DateTime::RFC1123);
31
        $b64Salt = \base64_encode($salt);
32
33
        return "{$hash}\n{$httpMethod}+{$uri}\n{$time}\n{$b64Salt}";
34
    }
35
36
    /**
37
     * Serializes the payload for signing
38
     *
39
     * @param array|string $payload
40
     * @return string
41
     */
42
    private static function serializePayload($payload = '') : string
43
    {
44
        // If the payload is already JSON, return it
45
        if (\is_string($payload)) {
46
            return $payload;
47
        }
48
49
        $data = '';
50
51
        if (!empty($payload)) {
52
            $data = \json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION);
53
        }
54
55
        return $data;
56
    }
57
58
    /**
59
     * Returns the signature hash
60
     *
61
     * @param string  $data
62
     * @param string  $salt
63
     * @param integer $version
64
     * @return string
65
     */
66
    private static function getSignatureHash(string $data, string $salt, int $version = 2) : string
67
    {
68
        if ($version === 2) {
69
            return \base64_encode(\sodium_crypto_generichash($data, $salt, 64));
70
        }
71
72
        // Version 1 signature hash should be returned as a fallback
73
        return \hash('sha256', $data);
74
    }
75
}
76