Completed
Pull Request — master (#1102)
by
unknown
08:28
created

CryptKey   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 103
Duplicated Lines 0 %

Test Coverage

Coverage 45.45%

Importance

Changes 8
Bugs 0 Features 0
Metric Value
eloc 35
c 8
b 0
f 0
dl 0
loc 103
ccs 15
cts 33
cp 0.4545
rs 10
wmc 14

4 Methods

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