JWK   A
last analyzed

Complexity

Total Complexity 7

Size/Duplication

Total Lines 106
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 7
lcom 1
cbo 2
dl 0
loc 106
ccs 0
cts 52
cp 0
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 20 4
A getPublicKey() 0 35 1
A encodeLength() 0 9 2
1
<?php
2
/**
3
 * @author Patsura Dmitry https://github.com/ovr <[email protected]>
4
 */
5
6
7
namespace SocialConnect\OpenIDConnect;
8
9
use SocialConnect\OpenIDConnect\Exception\InvalidJWK;
10
11
class JWK
12
{
13
    /**
14
     * @link https://tools.ietf.org/html/rfc7517#section-4.1
15
     *
16
     * The "kty" (key type) parameter identifies the cryptographic algorithm
17
     * family used with the key, such as "RSA" or "EC"
18
     *
19
     * @var string
20
     */
21
    protected $kty;
22
23
    /**
24
     * @var string
25
     */
26
    protected $n;
27
28
    /**
29
     * @var string
30
     */
31
    protected $e;
32
33
    /**
34
     * @param array $parameters
35
     * @throws InvalidJWK
36
     */
37
    public function __construct($parameters)
38
    {
39
        if (!isset($parameters['kty'])) {
40
            throw new InvalidJWK('Unknown kty');
41
        }
42
43
        $this->kty = $parameters['kty'];
44
45
        if (!isset($parameters['n'])) {
46
            throw new InvalidJWK('Unknown n');
47
        }
48
49
        $this->n = $parameters['n'];
50
51
        if (!isset($parameters['e'])) {
52
            throw new InvalidJWK('Unknown e');
53
        }
54
55
        $this->e = $parameters['e'];
56
    }
57
58
    /**
59
     * @return string
60
     */
61
    public function getPublicKey()
62
    {
63
        $modulus = JWT::urlsafeB64Decode($this->n);
64
        $publicExponent = JWT::urlsafeB64Decode($this->e);
65
66
        $components = array(
67
            'modulus' => pack('Ca*a*', 2, self::encodeLength(strlen($modulus)), $modulus),
68
            'publicExponent' => pack('Ca*a*', 2, self::encodeLength(strlen($publicExponent)), $publicExponent)
69
        );
70
71
        $publicKey = pack(
72
            'Ca*a*a*',
73
            48,
74
            self::encodeLength(strlen($components['modulus']) + strlen($components['publicExponent'])),
75
            $components['modulus'],
76
            $components['publicExponent']
77
        );
78
79
        // sequence(oid(1.2.840.113549.1.1.1), null)) = rsaEncryption.
80
        $rsaOID = pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA
81
        $publicKey = chr(0) . $publicKey;
82
        $publicKey = chr(3) . self::encodeLength(strlen($publicKey)) . $publicKey;
83
        $publicKey = pack(
84
            'Ca*a*',
85
            48,
86
            self::encodeLength(strlen($rsaOID . $publicKey)),
87
            $rsaOID . $publicKey
88
        );
89
90
        $publicKey = "-----BEGIN PUBLIC KEY-----\r\n" .
91
            chunk_split(base64_encode($publicKey), 64) .
92
            '-----END PUBLIC KEY-----';
93
94
        return $publicKey;
95
    }
96
97
    /**
98
     * DER-encode the length
99
     *
100
     * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4.  See
101
     * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
102
     *
103
     * @access private
104
     * @param int $length
105
     * @return string
106
     */
107
    private static function encodeLength($length)
108
    {
109
        if ($length <= 0x7F) {
110
            return chr($length);
111
        }
112
113
        $temp = ltrim(pack('N', $length), chr(0));
114
        return pack('Ca*', 0x80 | strlen($temp), $temp);
115
    }
116
}
117