Completed
Pull Request — master (#910)
by Andrew
01:49
created

CryptKey::__construct()   B

Complexity

Conditions 7
Paths 16

Size

Total Lines 29

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 8.0504

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 29
ccs 13
cts 18
cp 0.7221
rs 8.5226
cc 7
nc 16
nop 3
crap 8.0504
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
class CryptKey
15
{
16
    const RSA_KEY_PATTERN =
17
        '/^(-----BEGIN (RSA )?(PUBLIC|PRIVATE) KEY-----)\R.*(-----END (RSA )?(PUBLIC|PRIVATE) KEY-----)\R?$/s';
18
19
    /**
20
     * @var string
21
     */
22
    protected $keyPath;
23
24
    /**
25
     * @var null|string
26
     */
27
    protected $passPhrase;
28
29
    /**
30
     * @param string      $keyPath
31
     * @param null|string $passPhrase
32
     * @param bool        $keyPermissionsCheck
33
     */
34 37
    public function __construct($keyPath, $passPhrase = null, $keyPermissionsCheck = true)
35
    {
36 37
        if (preg_match(self::RSA_KEY_PATTERN, $keyPath)) {
37 1
            $keyPath = $this->saveKeyToFile($keyPath);
38
        }
39
40 37
        if (strpos($keyPath, 'file://') !== 0) {
41 2
            $keyPath = 'file://' . $keyPath;
42
        }
43
44 37
        if (!file_exists($keyPath) || !is_readable($keyPath)) {
45 1
            throw new \LogicException(sprintf('Key path "%s" does not exist or is not readable', $keyPath));
46
        }
47
48 36
        if ($keyPermissionsCheck === true) {
49
            // Verify the permissions of the key
50 36
            $keyPathPerms = decoct(fileperms($keyPath) & 0777);
51 36
            if (in_array($keyPathPerms, ['400', '440', '600', '640', '660'], true) === false) {
52
                trigger_error(sprintf(
53
                    'Key file "%s" permissions are not correct, recommend changing to 600 or 660 instead of %s',
54
                    $keyPath,
55
                    $keyPathPerms
56
                ), E_USER_NOTICE);
57
            }
58
        }
59
60 36
        $this->keyPath = $keyPath;
61 36
        $this->passPhrase = $passPhrase;
62 36
    }
63
64
    /**
65
     * @param string $key
66
     *
67
     * @throws \RuntimeException
68
     *
69
     * @return string
70
     */
71 1
    private function saveKeyToFile($key)
72
    {
73 1
        $tmpDir = sys_get_temp_dir();
74 1
        $keyPath = $tmpDir . '/' . sha1($key) . '.key';
75
76 1
        if (file_exists($keyPath)) {
77
            return 'file://' . $keyPath;
78
        }
79
80 1
        if (!touch($keyPath)) {
81
            // @codeCoverageIgnoreStart
82
            throw new \RuntimeException(sprintf('"%s" key file could not be created', $keyPath));
83
            // @codeCoverageIgnoreEnd
84
        }
85
86 1
        if (file_put_contents($keyPath, $key) === false) {
87
            // @codeCoverageIgnoreStart
88
            throw new \RuntimeException(sprintf('Unable to write key file to temporary directory "%s"', $tmpDir));
89
            // @codeCoverageIgnoreEnd
90
        }
91
92 1
        if (chmod($keyPath, 0600) === false) {
93
            // @codeCoverageIgnoreStart
94
            throw new \RuntimeException(sprintf('The key file "%s" file mode could not be changed with chmod to 600', $keyPath));
95
            // @codeCoverageIgnoreEnd
96
        }
97
98 1
        return 'file://' . $keyPath;
99
    }
100
101
    /**
102
     * Retrieve key path.
103
     *
104
     * @return string
105
     */
106 12
    public function getKeyPath()
107
    {
108 12
        return $this->keyPath;
109
    }
110
111
    /**
112
     * Retrieve key pass phrase.
113
     *
114
     * @return null|string
115
     */
116 10
    public function getPassPhrase()
117
    {
118 10
        return $this->passPhrase;
119
    }
120
}
121