Passed
Pull Request — master (#1196)
by
unknown
68:46 queued 33:46
created

CryptKey::saveKeyToFile()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 22
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4.0312

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 4
eloc 9
nc 4
nop 1
dl 0
loc 22
ccs 7
cts 8
cp 0.875
crap 4.0312
rs 9.9666
c 2
b 0
f 0

2 Methods

Rating   Name   Duplication   Size   Complexity  
A CryptKey::getKeyPath() 0 3 1
A CryptKey::isFilePath() 0 3 1
1
<?php
2
/**
3
 * Cryptography key holder.
4
 *
5
 * @author      Julián Gutiérrez <[email protected]>
6
 * @copyright   Copyright (c) Alex Bilbie
7
 * @license     http://mit-license.org/
8
 *
9
 * @link        https://github.com/thephpleague/oauth2-server
10
 */
11
12
namespace League\OAuth2\Server;
13
14
use Lcobucci\JWT\Signer\Key\InMemory;
15
use Lcobucci\JWT\Signer\Key\LocalFileReference;
16
use LogicException;
17
18
class CryptKey
19
{
20
    const RSA_KEY_PATTERN =
21
        '/^(-----BEGIN (RSA )?(PUBLIC|PRIVATE) KEY-----)\R.*(-----END (RSA )?(PUBLIC|PRIVATE) KEY-----)\R?$/s';
22
23
    const FILE_PREFIX = 'file://';
24
25
    /**
26
     * @var string
27
     */
28
    protected $keyPath;
29
30
    /**
31
     * @var null|string
32
     */
33
    protected $passPhrase;
34
35
    /**
36
     * @param string      $keyPath
37 56
     * @param null|string $passPhrase
38
     * @param bool        $keyPermissionsCheck
39 56
     */
40 1
    public function __construct($keyPath, $passPhrase = null, $keyPermissionsCheck = true)
41 55
    {
42 1
        $this->keyPath = $keyPath;
43 1
        $this->passPhrase = $passPhrase;
44
45
        if (\is_file($this->keyPath) && !$this->isFilePath()) {
46
            $this->keyPath = self::FILE_PREFIX . $this->keyPath;
47 55
        }
48 2
49
        if ($this->isFilePath()) {
50
            if (!\file_exists($keyPath) || !\is_readable($keyPath)) {
51 55
                throw new LogicException(\sprintf('Key path "%s" does not exist or is not readable', $keyPath));
52 1
            }
53
54
            if ($keyPermissionsCheck === true && PHP_OS_FAMILY !== 'Windows') {
55 54
                // Verify the permissions of the key
56
                $keyPathPerms = \decoct(\fileperms($keyPath) & 0777);
57 54
                if (\in_array($keyPathPerms, ['400', '440', '600', '640', '660'], true) === false) {
58 54
                    \trigger_error(
59
                        \sprintf(
60
                            'Key file "%s" permissions are not correct, recommend changing to 600 or 660 instead of %s',
61
                            $keyPath,
62
                            $keyPathPerms
63
                        ),
64
                        E_USER_NOTICE
65
                    );
66
                }
67 54
            }
68 54
        } else {
69 54
            $rsaMatch = \preg_match(static::RSA_KEY_PATTERN, $this->keyPath);
70
            if ($rsaMatch === 0) {
71
                throw new LogicException('This is not a RSA key');
72
            }
73
74
            if ($rsaMatch === false) {
75
                throw new \RuntimeException(
76
                    \sprintf('PCRE error [%d] encountered during key match attempt', \preg_last_error())
77
                );
78 1
            }
79
        }
80 1
    }
81 1
82
    public function isFilePath(): bool
83 1
    {
84
        return \strpos($this->keyPath, self::FILE_PREFIX) === 0;
85
    }
86
87 1
    /**
88
     * Retrieve key path.
89
     *
90
     * @return string
91
     */
92
    public function getKeyPath()
93 1
    {
94
        return $this->keyPath;
95
    }
96
97
    /**
98
     * Retrieve key pass phrase.
99 1
     *
100
     * @return null|string
101
     */
102
    public function getPassPhrase()
103
    {
104
        return $this->passPhrase;
105
    }
106
107 19
    /**
108
     * Create signer key
109 19
     *
110
     * @internal Remove when the JWT configuration is moved to the dependency injection container
111
     *
112
     * @return \Lcobucci\JWT\Signer\Key
113
     */
114
    public function createSignerKey(): \Lcobucci\JWT\Signer\Key
115
    {
116
        if ($this->isFilePath()) {
117 10
            return LocalFileReference::file($this->keyPath, $this->passPhrase ?? '');
118
        }
119 10
120
        return InMemory::plainText($this->keyPath, $this->passPhrase ?? '');
121
    }
122
}
123