Completed
Push — master ( bf7084...09c167 )
by Alex
35:09
created

CryptTrait::setEncryptionKey()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
/**
3
 * Public/private key encryption.
4
 *
5
 * @author      Alex Bilbie <[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 Defuse\Crypto\Crypto;
15
16
trait CryptTrait
17
{
18
    /**
19
     * @var CryptKey
20
     */
21
    protected $privateKey;
22
23
    /**
24
     * @var CryptKey
25
     */
26
    protected $publicKey;
27
28
    /**
29
     * @var string
30
     */
31
    protected $encryptionKey;
32
33
    /**
34
     * Set path to private key.
35
     *
36
     * @param CryptKey $privateKey
37
     */
38
    public function setPrivateKey(CryptKey $privateKey)
39
    {
40
        $this->privateKey = $privateKey;
41
    }
42
43
    /**
44
     * Set path to public key.
45
     *
46
     * @param CryptKey $publicKey
47
     */
48
    public function setPublicKey(CryptKey $publicKey)
49
    {
50
        $this->publicKey = $publicKey;
51
    }
52
53
    /**
54
     * Encrypt data with a private key.
55
     *
56
     * @param string $unencryptedData
57
     *
58
     * @throws \LogicException
59
     *
60
     * @return string
61
     */
62
    protected function encrypt($unencryptedData)
63
    {
64
        if ($this->encryptionKey !== null) {
65
            return Crypto::encryptWithPassword($unencryptedData, $this->encryptionKey);
66
        }
67
68
        $privateKey = openssl_pkey_get_private($this->privateKey->getKeyPath(), $this->privateKey->getPassPhrase());
69
        $privateKeyDetails = @openssl_pkey_get_details($privateKey);
70
        if ($privateKeyDetails === null) {
71
            throw new \LogicException(
72
                sprintf('Could not get details of private key: %s', $this->privateKey->getKeyPath())
73
            );
74
        }
75
76
        $chunkSize = ceil($privateKeyDetails['bits'] / 8) - 11;
77
        $output = '';
78
79
        while ($unencryptedData) {
80
            $chunk = substr($unencryptedData, 0, $chunkSize);
81
            $unencryptedData = substr($unencryptedData, $chunkSize);
82
            if (openssl_private_encrypt($chunk, $encrypted, $privateKey) === false) {
83
                // @codeCoverageIgnoreStart
84
                throw new \LogicException('Failed to encrypt data');
85
                // @codeCoverageIgnoreEnd
86
            }
87
            $output .= $encrypted;
88
        }
89
        openssl_pkey_free($privateKey);
90
91
        return base64_encode($output);
92
    }
93
94
    /**
95
     * Decrypt data with a public key.
96
     *
97
     * @param string $encryptedData
98
     *
99
     * @throws \LogicException
100
     *
101
     * @return string
102
     */
103
    protected function decrypt($encryptedData)
104
    {
105
        if ($this->encryptionKey !== null) {
106
            return Crypto::decryptWithPassword($encryptedData, $this->encryptionKey);
107
        }
108
109
        $publicKey = openssl_pkey_get_public($this->publicKey->getKeyPath());
110
        $publicKeyDetails = @openssl_pkey_get_details($publicKey);
111
        if ($publicKeyDetails === null) {
112
            throw new \LogicException(
113
                sprintf('Could not get details of public key: %s', $this->publicKey->getKeyPath())
114
            );
115
        }
116
117
        $chunkSize = ceil($publicKeyDetails['bits'] / 8);
118
        $output = '';
119
120
        $encryptedData = base64_decode($encryptedData);
121
122
        while ($encryptedData) {
123
            $chunk = substr($encryptedData, 0, $chunkSize);
124
            $encryptedData = substr($encryptedData, $chunkSize);
125
            if (openssl_public_decrypt($chunk, $decrypted, $publicKey/*, OPENSSL_PKCS1_OAEP_PADDING*/) === false) {
126
                // @codeCoverageIgnoreStart
127
                throw new \LogicException('Failed to decrypt data');
128
                // @codeCoverageIgnoreEnd
129
            }
130
            $output .= $decrypted;
131
        }
132
        openssl_pkey_free($publicKey);
133
134
        return $output;
135
    }
136
137
    /**
138
     * Set the encryption key
139
     *
140
     * @param string $key
141
     */
142
    public function setEncryptionKey($key = null)
143
    {
144
        $this->encryptionKey = $key;
145
    }
146
}
147