Completed
Push — master ( 9af5c5...a59dfb )
by Jonathan
06:17
created

EnvelopeEncryptingItemDecorator::signString()   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;
3
4
use Psr\Cache\CacheItemInterface;
5
6
class EnvelopeEncryptingItemDecorator extends EncryptingItemDecorator
7
{
8
    /** @var resource */
9
    private $publicKey;
10
    /** @var resource */
11
    private $privateKey;
12
13 171
    public function __construct(
14
        CacheItemInterface $decorated,
15
        $certificate,
16
        $key,
17
        $passPhrase,
18
        $cipher
19
    ) {
20 171
        parent::__construct($decorated, $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
            && $this->validateSignature(
37 93
                $this->getKey() . $data->getCipherText(),
38 93
                $data->getSignature()
39 132
            );
40
    }
41
42 111
    protected function encrypt($data)
43
    {
44 111
        $key = $this->generateIv();
45 111
        $iv = $this->generateIv();
46 111
        $cipherText = $this->encryptString(serialize($data), $key, $iv);
47
48 111
        return new EnvelopeEncryptedValue(
49 111
            $cipherText,
50 111
            $this->getCipherMethod(),
51 111
            $iv,
52 111
            $this->encryptEnvelopeKey($key),
53 111
            $this->signString($this->getKey() . $cipherText)
54 111
        );
55
    }
56
57 66
    protected function decrypt(EncryptedValue $data)
58
    {
59 66
        if (!$data instanceof EnvelopeEncryptedValue) return null;
60
61 66
        return unserialize($this->decryptString(
62 66
            $data->getCipherText(),
63 66
            $data->getMethod(),
64 66
            $this->decryptEnvelopeKey($data->getEnvelopeKey()),
65 66
            $data->getInitializationVector()
66 66
        ));
67
    }
68
69 171
    private function setPublicKey($cert)
70
    {
71 171
        $publicKey = @openssl_pkey_get_public($cert);
72 171
        if (!$this->validateOpenSslKey($publicKey)) {
73 6
            throw new InvalidArgumentException('Unable to create public key'
74
                . ' from provided certificate. Certificate must be a valid x509'
75 6
                . ' certificate, a PEM encoded certificate, or a path to a file'
76 6
                . ' containing a PEM encoded certificate.');
77
        }
78
79 165
        $this->publicKey = $publicKey;
80 165
    }
81
82 165
    private function setPrivateKey($key, $passPhrase)
83
    {
84 165
        $this->privateKey = @openssl_pkey_get_private($key, $passPhrase);
85 165
        if (!$this->validateOpenSslKey($this->privateKey)) {
86 3
            throw new InvalidArgumentException('Unable to create private key'
87
                . ' from provided key. Key must be a PEM encoded private key or'
88 3
                . ' a path to a file containing a PEM encoded private key.');
89
        }
90 162
    }
91
92 171
    private function validateOpenSslKey($key)
93
    {
94 171
        return is_resource($key) && 'OpenSSL key' === get_resource_type($key);
95
    }
96
97 111
    private function signString($string)
98
    {
99 111
        openssl_sign($string, $signature, $this->privateKey);
100
101 111
        return $signature;
102
    }
103
104 93
    private function validateSignature($signed, $signature)
105
    {
106 93
        return openssl_verify($signed, $signature, $this->publicKey);
107
    }
108
109 111
    private function encryptEnvelopeKey($key)
110
    {
111 111
        openssl_public_encrypt($key, $sealedKey, $this->publicKey);
112
113 111
        return $sealedKey;
114
    }
115
116 66
    private function decryptEnvelopeKey($sealedKey)
117
    {
118 66
        openssl_private_decrypt($sealedKey, $key, $this->privateKey);
119
120 66
        return $key;
121
    }
122
}
123