Completed
Push — master ( 1de13c...bf55ce )
by Alex
33:38
created

CryptTrait::decrypt()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 29
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
c 2
b 1
f 0
dl 0
loc 29
rs 8.5806
cc 4
eloc 17
nc 4
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
namespace League\OAuth2\Server;
12
13
trait CryptTrait
14
{
15
    /**
16
     * @var \League\OAuth2\Server\CryptKey
17
     */
18
    protected $privateKey;
19
20
    /**
21
     * @var \League\OAuth2\Server\CryptKey
22
     */
23
    protected $publicKey;
24
25
    /**
26
     * Set path to private key.
27
     *
28
     * @param \League\OAuth2\Server\CryptKey $privateKey
29
     */
30
    public function setPrivateKey(CryptKey $privateKey)
31
    {
32
        $this->privateKey = $privateKey;
33
    }
34
35
    /**
36
     * Set path to public key.
37
     *
38
     * @param \League\OAuth2\Server\CryptKey $publicKey
39
     */
40
    public function setPublicKey(CryptKey $publicKey)
41
    {
42
        $this->publicKey = $publicKey;
43
    }
44
45
    /**
46
     * Encrypt data with a private key.
47
     *
48
     * @param string $unencryptedData
49
     *
50
     * @return string
51
     */
52
    protected function encrypt($unencryptedData)
53
    {
54
        $privateKey = openssl_pkey_get_private($this->privateKey->getKeyPath(), $this->privateKey->getPassPhrase());
55
        $privateKeyDetails = @openssl_pkey_get_details($privateKey);
56
        if ($privateKeyDetails === null) {
57
            throw new \LogicException(
58
                sprintf('Could not get details of private key: %s', $this->privateKey->getKeyPath())
59
            );
60
        }
61
62
        $chunkSize = ceil($privateKeyDetails['bits'] / 8) - 11;
63
        $output = '';
64
65
        while ($unencryptedData) {
66
            $chunk = substr($unencryptedData, 0, $chunkSize);
67
            $unencryptedData = substr($unencryptedData, $chunkSize);
68
            if (openssl_private_encrypt($chunk, $encrypted, $privateKey) === false) {
69
                // @codeCoverageIgnoreStart
70
                throw new \LogicException('Failed to encrypt data');
71
                // @codeCoverageIgnoreEnd
72
            }
73
            $output .= $encrypted;
74
        }
75
        openssl_pkey_free($privateKey);
76
77
        return base64_encode($output);
78
    }
79
80
    /**
81
     * Decrypt data with a public key.
82
     *
83
     * @param string $encryptedData
84
     *
85
     * @throws \LogicException
86
     *
87
     * @return string
88
     */
89
    protected function decrypt($encryptedData)
90
    {
91
        $publicKey = openssl_pkey_get_public($this->publicKey->getKeyPath());
92
        $publicKeyDetails = @openssl_pkey_get_details($publicKey);
93
        if ($publicKeyDetails === null) {
94
            throw new \LogicException(
95
                sprintf('Could not get details of public key: %s', $this->publicKey->getKeyPath())
96
            );
97
        }
98
99
        $chunkSize = ceil($publicKeyDetails['bits'] / 8);
100
        $output = '';
101
102
        $encryptedData = base64_decode($encryptedData);
103
104
        while ($encryptedData) {
105
            $chunk = substr($encryptedData, 0, $chunkSize);
106
            $encryptedData = substr($encryptedData, $chunkSize);
107
            if (openssl_public_decrypt($chunk, $decrypted, $publicKey/*, OPENSSL_PKCS1_OAEP_PADDING*/) === false) {
108
                // @codeCoverageIgnoreStart
109
                throw new \LogicException('Failed to decrypt data');
110
                // @codeCoverageIgnoreEnd
111
            }
112
            $output .= $decrypted;
113
        }
114
        openssl_pkey_free($publicKey);
115
116
        return $output;
117
    }
118
}
119