Completed
Pull Request — master (#997)
by TEst
02:35 queued 48s
created

CryptKey   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 107
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 0

Test Coverage

Coverage 80.65%

Importance

Changes 0
Metric Value
wmc 14
lcom 0
cbo 0
dl 0
loc 107
ccs 25
cts 31
cp 0.8065
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
B __construct() 0 29 7
A saveKeyToFile() 0 29 5
A getKeyPath() 0 4 1
A getPassPhrase() 0 4 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 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 39
    public function __construct($keyPath, $passPhrase = null, $keyPermissionsCheck = true)
38
    {
39 39
        if (preg_match(self::RSA_KEY_PATTERN, $keyPath)) {
40 1
            $keyPath = $this->saveKeyToFile($keyPath);
41
        }
42
43 39
        if (strpos($keyPath, 'file://') !== 0) {
44 2
            $keyPath = 'file://' . $keyPath;
45
        }
46
47 39
        if (!file_exists($keyPath) || !is_readable($keyPath)) {
48 1
            throw new LogicException(sprintf('Key path "%s" does not exist or is not readable', $keyPath));
49
        }
50
51 38
        if ($keyPermissionsCheck === true) {
52
            // Verify the permissions of the key
53 38
            $keyPathPerms = decoct(fileperms($keyPath) & 0777);
54 38
            if (in_array($keyPathPerms, ['400', '440', '600', '640', '660'], true) === false) {
55
                trigger_error(sprintf(
56
                    'Key file "%s" permissions are not correct, recommend changing to 600 or 660 instead of %s',
57
                    $keyPath,
58
                    $keyPathPerms
59
                ), E_USER_NOTICE);
60
            }
61
        }
62
63 38
        $this->keyPath = $keyPath;
64 38
        $this->passPhrase = $passPhrase;
65 38
    }
66
67
    /**
68
     * @param string $key
69
     *
70
     * @throws RuntimeException
71
     *
72
     * @return string
73
     */
74 1
    private function saveKeyToFile($key)
75
    {
76 1
        $tmpDir = sys_get_temp_dir();
77 1
        $keyPath = $tmpDir . '/' . sha1($key) . '.key';
78
79 1
        if (file_exists($keyPath)) {
80
            return 'file://' . $keyPath;
81
        }
82
83 1
        if (!touch($keyPath)) {
84
            // @codeCoverageIgnoreStart
85
            throw new RuntimeException(sprintf('"%s" key file could not be created', $keyPath));
86
            // @codeCoverageIgnoreEnd
87
        }
88
89 1
        if (file_put_contents($keyPath, $key) === false) {
90
            // @codeCoverageIgnoreStart
91
            throw new RuntimeException(sprintf('Unable to write key file to temporary directory "%s"', $tmpDir));
92
            // @codeCoverageIgnoreEnd
93
        }
94
95 1
        if (chmod($keyPath, 0600) === false) {
96
            // @codeCoverageIgnoreStart
97
            throw new RuntimeException(sprintf('The key file "%s" file mode could not be changed with chmod to 600', $keyPath));
98
            // @codeCoverageIgnoreEnd
99
        }
100
101 1
        return 'file://' . $keyPath;
102
    }
103
104
    /**
105
     * Retrieve key path.
106
     *
107
     * @return string
108
     */
109 14
    public function getKeyPath()
110
    {
111 14
        return $this->keyPath;
112
    }
113
114
    /**
115
     * Retrieve key pass phrase.
116
     *
117
     * @return null|string
118
     */
119 10
    public function getPassPhrase()
120
    {
121 10
        return $this->passPhrase;
122
    }
123
}
124