Completed
Push — master ( 789220...9af5c5 )
by Jonathan
04:43
created

EnvelopeEncryptingItemDecorator::setPublicKey()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2
Metric Value
dl 0
loc 12
ccs 8
cts 8
cp 1
rs 9.4286
cc 2
eloc 8
nc 2
nop 1
crap 2
1
<?php
2
namespace Jsq\Cache;
3
4
use Psr\Cache\CacheItemInterface;
5
6
class EnvelopeEncryptingItemDecorator extends EncryptingItemDecorator
7
{
8
    private $publicKey;
9
    private $privateKey;
10
    private $cipher;
11
12 171
    public function __construct(
13
        CacheItemInterface $decorated,
14
        $certificate,
15
        $key,
16
        $passPhrase,
17
        $cipher
18
    ) {
19 171
        parent::__construct($decorated);
20 171
        $this->cipher = $cipher;
21 171
        $this->setPublicKey($certificate);
22 165
        $this->setPrivateKey($key, $passPhrase);
23 162
    }
24
25 162
    public function __destruct()
26
    {
27 162
        openssl_pkey_free($this->publicKey);
28 162
        openssl_pkey_free($this->privateKey);
29 162
    }
30
31 132
    protected function isDecryptable()
32
    {
33 132
        $data = $this->getDecorated()->get();
34
35
        return $data instanceof EnvelopeEncryptedValue
36 132
            && openssl_verify(
37 93
                $this->getKey() . $data->getCipherText(),
38 93
                $data->getSignature(),
39 93
                $this->publicKey
40 132
            );
41
    }
42
43 111
    protected function encrypt($data)
44
    {
45 111
        $key = openssl_random_pseudo_bytes(
46 111
            openssl_cipher_iv_length($this->cipher)
47 111
        );
48 111
        $iv = openssl_random_pseudo_bytes(
49 111
            openssl_cipher_iv_length($this->cipher)
50 111
        );
51 111
        $cipherText = openssl_encrypt(
52 111
            serialize($data),
53 111
            $this->cipher,
54 111
            $key,
55 111
            0,
56
            $iv
57 111
        );
58
59 111
        openssl_sign(
60 111
            $this->getKey() . $cipherText,
61 111
            $signature,
62 111
            $this->privateKey
63 111
        );
64 111
        openssl_public_encrypt($key, $sealedKey, $this->publicKey);
65
66 111
        return new EnvelopeEncryptedValue(
67 111
            $cipherText,
68 111
            $this->cipher,
69 111
            $iv,
70 111
            $sealedKey,
71
            $signature
72 111
        );
73
    }
74
75 66
    protected function decrypt(EncryptedValue $data)
76
    {
77 66
        if (!$data instanceof EnvelopeEncryptedValue) return null;
78
79 66
        openssl_private_decrypt($data->getEnvelopeKey(), $key, $this->privateKey);
80
81 66
        return unserialize(openssl_decrypt(
82 66
            $data->getCipherText(),
83 66
            $data->getMethod(),
84 66
            $key,
85 66
            0,
86 66
            $data->getInitializationVector()
87 66
        ));
88
    }
89
90 171
    private function setPublicKey($cert)
91
    {
92 171
        $publicKey = @openssl_pkey_get_public($cert);
93 171
        if (!$this->validateOpenSslKey($publicKey)) {
94 6
            throw new InvalidArgumentException('Unable to create public key'
95
                . ' from provided certificate. Certificate must be a valid x509'
96 6
                . ' certificate, a PEM encoded certificate, or a path to a file'
97 6
                . ' containing a PEM encoded certificate.');
98
        }
99
100 165
        $this->publicKey = $publicKey;
101 165
    }
102
103 165
    private function setPrivateKey($key, $passPhrase)
104
    {
105 165
        $this->privateKey = @openssl_pkey_get_private($key, $passPhrase);
106 165
        if (!$this->validateOpenSslKey($this->privateKey)) {
107 3
            throw new InvalidArgumentException('Unable to create private key'
108
                . ' from provided key. Key must be a PEM encoded private key or'
109 3
                . ' a path to a file containing a PEM encoded private key.');
110
        }
111 162
    }
112
113 171
    private function validateOpenSslKey($key)
114
    {
115 171
        return is_resource($key) && 'OpenSSL key' === get_resource_type($key);
116
    }
117
}
118