1
<?php
2

3
declare(strict_types=1);
4

5
namespace ReallySimpleJWT;
6

7
use ReallySimpleJWT\Interfaces\Encoder;
8

9
/**
10
 * Class used to encode the JSON Web Token and signature.
11
 *
12
 * This class is written so it is replaceable with a custom encoding. See
13
 * the encoder interface.
14
 */
15
class Encode implements Encoder
16
{
17
    /**
18
     * The Algorithm which was used to hash the token signature. This is what
19
     * is displayed as the alg claim in the token header. Note this may be
20
     * slightly different from the actual algorithm used to hash the
21
     * signature string.
22
     */
23
    private const ALGORITHM = 'HS256';
24

25
    /**
26
     * This is the actual algorithm used to hash the token's signature string.
27
     */
28
    private const HASH_ALGORITHM = 'sha256';
29

30
    /**
31
     * Get the algorithm used to encode the signature. Note this is for show,
32
     * it is what is displayed in the JWT header as the alg claim.
33
     *
34
     * @return string
35
     */
36 1
    public function getAlgorithm(): string
37
    {
38 1
        return self::ALGORITHM;
39
    }
40

41
    /**
42
     * Get the hash algorithm string to be used when encoding the signature,
43
     * this is the actual hash type used to encode the signature.
44
     *
45
     * @return string
46
     */
47 1
    private function getHashAlgorithm(): string
48
    {
49 1
        return self::HASH_ALGORITHM;
50
    }
51

52
    /**
53
     * Encode a json string in Base64 Url format.
54
     *
55
     * @param string $toEncode
56
     * @return string
57
     */
58 1
    public function encode(string $toEncode): string
59
    {
60 1
        return $this->toBase64Url(base64_encode($toEncode));
61
    }
62

63
    /**
64
     * Decode a Base64 Url string to a json string
65
     *
66
     * @param string $toDecode
67
     * @return string
68
     */
69 1
    public function decode(string $toDecode): string
70
    {
71 1
        return (string) base64_decode(
72 1
            $this->addPadding($this->toBase64($toDecode)),
73 1
            true
74
        );
75
    }
76

77
    /**
78
     * Generate the JWT signature. The header and payload are encoded,
79
     * concatenated with a dot, hashed via sha256 with a secret, and then
80
     * encoded and returned.
81
     *
82
     * @param string $header
83
     * @param string $payload
84
     * @param string $secret
85
     * @return string
86
     */
87 1
    public function signature(string $header, string $payload, string $secret): string
88
    {
89 1
        return $this->encode(
90 1
            $this->hash(
91 1
                $this->getHashAlgorithm(),
92 1
                $this->encode($header) . "." . $this->encode($payload),
93
                $secret
94
            )
95
        );
96
    }
97

98
    /**
99
     * Hash the JWT signature string using sha256.
100
     *
101
     * @param string $algorithm
102
     * @param string $toHash
103
     * @param string $secret
104
     * @return string
105
     */
106 1
    private function hash(string $algorithm, string $toHash, string $secret): string
107
    {
108 1
        return hash_hmac($algorithm, $toHash, $secret, true);
109
    }
110

111
    /**
112
     * Convert a base64 string to a base64 Url string.
113
     *
114
     * @param string $base64
115
     * @return string
116
     */
117 1
    private function toBase64Url(string $base64): string
118
    {
119 1
        return str_replace(['+', '/', '='], ['-', '_', ''], $base64);
120
    }
121

122
    /**
123
     * Convert a base64 URL string to a base64 string.
124
     *
125
     * @param string $urlString
126
     * @return string
127
     */
128 1
    private function toBase64(string $urlString): string
129
    {
130 1
        return str_replace(['-', '_'], ['+', '/'], $urlString);
131
    }
132

133
    /**
134
     * Add padding to base64 strings which require it. Some base64 URL strings
135
     * which are decoded will have missing padding which is represented by the
136
     * equals sign.
137
     *
138
     * @param string $base64String
139
     * @return string
140
     */
141 1
    private function addPadding(string $base64String): string
142
    {
143 1
        if (strlen($base64String) % 4 !== 0) {
144 1
            return $this->addPadding($base64String . '=');
145
        }
146

147 1
        return $base64String;
148
    }
149
}

Read our documentation on viewing source code .

Loading