Decorator::isDataDecryptable()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 8
ccs 4
cts 4
cp 1
rs 9.4285
cc 2
eloc 5
nc 2
nop 2
crap 2
1
<?php
2
namespace Jsq\Cache\EnvelopeEncryption;
3
4
use Doctrine\Common\Cache\Cache;
5
use InvalidArgumentException as IAE;
6
use Jsq\Cache\EncryptedValue;
7
use Jsq\Cache\EncryptingDecorator;
8
9
class Decorator extends EncryptingDecorator
10
{
11
    /** @var resource */
12
    private $publicKey;
13
    /** @var resource */
14
    private $privateKey;
15
    /** @var string */
16
    private $cipher;
17
18
    /**
19
     * @param Cache $decorated
20
     * @param mixed $cert
21
     * @param mixed $key
22
     * @param string|null $passphrase
23
     * @param string $cipher
24
     *
25
     * @throws IAE If OpenSSL keys cannot be extracted from $cert and $key.
26 93
     */
27
    public function __construct(
28
        Cache $decorated,
29
        $cert,
30
        $key,
31
        $passphrase = null,
32
        $cipher = 'aes-256-cbc'
33 93
    ) {
34 93
        parent::__construct($decorated);
35 93
        $this->setPublicKey($cert);
36 93
        $this->setPrivateKey($key, $passphrase);
37 93
        $this->cipher = $cipher;
38
    }
39 57
40
    public function __destruct()
41 57
    {
42 57
        openssl_free_key($this->publicKey);
43 57
        openssl_free_key($this->privateKey);
44
    }
45 57
46
    protected function isDataDecryptable($data, string $id): bool
47
    {
48 57
        return $data instanceof Value
49 18
            && $this->validateSignature(
50 18
                $id . $data->getCipherText(),
51 57
                $data->getSignature()
52
            );
53
    }
54 36
55
    protected function encrypt($data, string $id): EncryptedValue
56 36
    {
57 36
        $key = $this->generateIv($this->cipher);
58 36
        $iv = $this->generateIv($this->cipher);
59
        $cipherText = $this->encipher(serialize($data), $this->cipher, $key, $iv);
60 36
61 36
        return new Value(
62 36
            $cipherText,
63 36
            $this->cipher,
64 36
            $iv,
65 36
            $this->encryptEnvelopeKey($key),
66 36
            $this->signString($id . $cipherText)
67
        );
68
    }
69 18
70 View Code Duplication
    protected function decrypt($data)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
71 18
    {
72
        if (!$data instanceof Value) return false;
73 18
74 18
        return unserialize($this->decipher(
75 18
            $data->getCipherText(),
76 18
            $data->getMethod(),
77 18
            $this->decryptEnvelopeKey($data->getEnvelopeKey()),
78 18
            $data->getInitializationVector()
79
        ));
80
    }
81 93
82
    private function setPublicKey($cert)
83 93
    {
84 93
        $this->publicKey = @openssl_pkey_get_public($cert);
85 6
        if (!$this->validateOpenSslKey($this->publicKey)) {
86
            throw new IAE('Unable to create public key from provided'
87 6
                . ' certificate. Certificate must be a valid x509 certificate,'
88 6
                . ' a PEM encoded certificate, or a path to a file containing a'
89
                . ' PEM encoded certificate.');
90 93
        }
91
    }
92 93
93
    private function setPrivateKey($key, $passphrase)
94 93
    {
95 93
        $this->privateKey = @openssl_pkey_get_private($key, $passphrase);
96 3
        if (!$this->validateOpenSslKey($this->privateKey)) {
97
            throw new IAE('Unable to create private key from provided key. Key'
98 3
                . ' must be a PEM encoded private key or a path to a file'
99
                . ' containing a PEM encoded private key.');
100 93
        }
101
    }
102 93
103
    private function validateOpenSslKey($key)
104 93
    {
105
        return is_resource($key) && 'OpenSSL key' === get_resource_type($key);
106
    }
107 36
108
    private function signString($string)
109 36
    {
110
        openssl_sign($string, $signature, $this->privateKey);
111 36
112
        return $signature;
113
    }
114 18
115
    private function validateSignature($signed, $signature)
116 18
    {
117
        return openssl_verify($signed, $signature, $this->publicKey);
118
    }
119 36
120
    private function encryptEnvelopeKey($key)
121 36
    {
122
        openssl_public_encrypt($key, $sealedKey, $this->publicKey);
123 36
124
        return $sealedKey;
125
    }
126 18
127
    private function decryptEnvelopeKey($sealedKey)
128 18
    {
129
        openssl_private_decrypt($sealedKey, $key, $this->privateKey);
130 18
131
        return $key;
132
    }
133
}
134