Completed
Push — master ( a59dfb...8ffece )
by Jonathan
10:03
created

EncryptingItemDecorator::decryptEnvelopeKey()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

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