Passed
Push — master ( e9ba59...c2c890 )
by Tony Karavasilev (Тони
19:20
created

DigitalEnvelope::__construct()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 10
c 1
b 0
f 0
dl 0
loc 16
ccs 0
cts 14
cp 0
rs 9.9332
cc 3
nc 3
nop 2
crap 12
1
<?php
2
3
/**
4
 * Cryptographic digital envelope protocol for secure data transfers.
5
 */
6
7
namespace CryptoManana\CryptographicProtocol;
8
9
use \CryptoManana\Core\Abstractions\Containers\AbstractCryptographicProtocol as CryptographicProtocol;
10
use \CryptoManana\Core\Abstractions\Randomness\AbstractRandomness as RandomnessSource;
11
use \CryptoManana\Core\Abstractions\Randomness\AbstractGenerator as RandomnessGenerator;
12
use \CryptoManana\Core\Abstractions\MessageDigestion\AbstractKeyedHashFunction as KeyedHashFunction;
13
use \CryptoManana\Core\Abstractions\MessageEncryption\AbstractBlockCipherAlgorithm as SymmetricBlockCipher;
14
use \CryptoManana\Core\Abstractions\MessageEncryption\AbstractAsymmetricEncryptionAlgorithm as AsymmetricEncryption;
15
use \CryptoManana\Core\Interfaces\MessageEncryption\DataEncryptionInterface as DataEncryption;
16
use \CryptoManana\Core\Interfaces\Containers\DigitalEnvelopeInterface as DigitalEnvelopeProcessing;
17
use \CryptoManana\Core\Interfaces\Containers\RandomnessInjectableInterface as RandomGeneratorSetter;
18
use \CryptoManana\Core\Interfaces\Containers\KeyedDigestionInjectableInterface as KeyedHashFunctionSetter;
19
use \CryptoManana\Core\Interfaces\Containers\SymmetricEncryptionInjectableInterface as SymmetricCipherSetter;
20
use \CryptoManana\Core\Interfaces\Containers\AsymmetricEncryptionInjectableInterface as AsymmetricCipherSetter;
21
use \CryptoManana\Core\Traits\Containers\RandomnessInjectableTrait as RandomGeneratorSetterImplementation;
22
use \CryptoManana\Core\Traits\Containers\KeyedDigestionInjectableTrait as KeyedHashFunctionSetterImplementation;
23
use \CryptoManana\Core\Traits\Containers\SymmetricEncryptionInjectableTrait as SymmetricCipherSetterImplementation;
24
use \CryptoManana\Core\Traits\Containers\AsymmetricEncryptionInjectableTrait as AsymmetricCipherSetterImplementation;
25
use \CryptoManana\Randomness\CryptoRandom as DefaultRandomnessSource;
26
use \CryptoManana\DataStructures\EnvelopeData as EnvelopeStructure;
27
28
/**
29
 * Class DigitalEnvelope - The digital envelope cryptographic protocol object.
30
 *
31
 * @package CryptoManana\CryptographicProtocol
32
 *
33
 * @mixin RandomGeneratorSetterImplementation
34
 * @mixin KeyedHashFunctionSetterImplementation
35
 * @mixin SymmetricCipherSetterImplementation
36
 * @mixin AsymmetricCipherSetterImplementation
37
 */
38
class DigitalEnvelope extends CryptographicProtocol implements
39
    RandomGeneratorSetter,
40
    KeyedHashFunctionSetter,
41
    SymmetricCipherSetter,
42
    AsymmetricCipherSetter,
43
    DigitalEnvelopeProcessing
44
{
45
    /**
46
     * Dependency injection via a setter method implementation.
47
     *
48
     * {@internal Reusable implementation of `RandomnessInjectableInterface`. }}
49
     */
50
    use RandomGeneratorSetterImplementation;
51
52
    /**
53
     * The message keyed digestion service dependency injection via a setter method implementation.
54
     *
55
     * {@internal Reusable implementation of `KeyedDigestionInjectableInterface`. }}
56
     */
57
    use KeyedHashFunctionSetterImplementation;
58
59
    /**
60
     * The message symmetric encryption service dependency injection via a setter method implementation.
61
     *
62
     * {@internal Reusable implementation of `SymmetricEncryptionInjectableInterface`. }}
63
     */
64
    use SymmetricCipherSetterImplementation;
65
66
    /**
67
     * The message asymmetric encryption service dependency injection via a setter method.
68
     *
69
     * {@internal Reusable implementation of `AsymmetricEncryptionInjectableInterface`. }}
70
     */
71
    use AsymmetricCipherSetterImplementation;
72
73
    /**
74
     * The pseudo-random generator service property storage.
75
     *
76
     * @var RandomnessSource|RandomnessGenerator|null The pseudo-random generator service.
77
     */
78
    protected $randomnessSource = null;
79
80
    /**
81
     * The message keyed digestion service property storage.
82
     *
83
     * @var KeyedHashFunction|null The message keyed digestion service.
84
     */
85
    protected $keyedDigestionSource = null;
86
87
    /**
88
     * The message encryption symmetric algorithm service property storage.
89
     *
90
     * @var SymmetricBlockCipher|DataEncryption|null The symmetric message encryption service.
91
     */
92
    protected $symmetricCipherSource = null;
93
94
    /**
95
     * The message asymmetric encryption algorithm service property storage.
96
     *
97
     * @var AsymmetricEncryption|DataEncryption|null The message asymmetric encryption service.
98
     */
99
    protected $asymmetricCipherSource = null;
100
101
    /**
102
     * Container constructor.
103
     *
104
     * @param AsymmetricEncryption|DataEncryption|null $asymmetric The asymmetric message encryption service.
105
     * @param SymmetricBlockCipher|null $symmetric the message encryption service.
106
     *
107
     * @throws \Exception Initialization validation.
108
     */
109
    public function __construct(AsymmetricEncryption $asymmetric = null, SymmetricBlockCipher $symmetric = null)
110
    {
111
        if ($asymmetric instanceof DataEncryption) {
112
            $this->asymmetricCipherSource = $asymmetric;
113
        } else {
114
            throw new \RuntimeException('No asymmetric encryption service has been set.');
115
        }
116
117
        if ($symmetric instanceof DataEncryption) {
118
            $this->symmetricCipherSource = $symmetric;
119
        } else {
120
            throw new \RuntimeException('No symmetric encryption service has been set.');
121
        }
122
123
        $this->randomnessSource = new DefaultRandomnessSource();
124
        $this->keyedDigestionSource = null;
125
    }
126
127
    /**
128
     * Container destructor.
129
     */
130
    public function __destruct()
131
    {
132
        unset(
133
            $this->randomnessSource,
134
            $this->keyedDigestionSource,
135
            $this->symmetricCipherSource,
136
            $this->asymmetricCipherSource
137
        );
138
    }
139
140
    /**
141
     * Container cloning via deep copy.
142
     */
143
    public function __clone()
144
    {
145
        $this->randomnessSource = clone $this->randomnessSource;
146
        $this->symmetricCipherSource = clone $this->symmetricCipherSource;
147
        $this->asymmetricCipherSource = clone $this->asymmetricCipherSource;
148
149
        if ($this->keyedDigestionSource !== null) {
150
            $this->keyedDigestionSource = clone $this->keyedDigestionSource;
151
        }
152
    }
153
154
    /**
155
     * Seals the envelope with the secured information inside.
156
     *
157
     * @param string $plainData The plain message information.
158
     *
159
     * @return EnvelopeStructure The sealed envelope object.
160
     * @throws \Exception Validation errors.
161
     */
162
    public function sealEnvelope($plainData)
163
    {
164
        $key = $this->randomnessSource->getBytes(64);
1 ignored issue
show
Bug introduced by
The method getBytes() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

164
        /** @scrutinizer ignore-call */ 
165
        $key = $this->randomnessSource->getBytes(64);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
165
        $iv = $this->randomnessSource->getBytes(64);
166
167
        $this->symmetricCipherSource->setSecretKey($key)->setInitializationVector($iv);
3 ignored issues
show
Bug introduced by
The method setSecretKey() does not exist on CryptoManana\Core\Interf...DataEncryptionInterface. It seems like you code against a sub-type of CryptoManana\Core\Interf...DataEncryptionInterface such as CryptoManana\Core\Abstra...tricEncryptionAlgorithm. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

167
        $this->symmetricCipherSource->/** @scrutinizer ignore-call */ 
168
                                      setSecretKey($key)->setInitializationVector($iv);
Loading history...
Bug introduced by
The method setSecretKey() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

167
        $this->symmetricCipherSource->/** @scrutinizer ignore-call */ 
168
                                      setSecretKey($key)->setInitializationVector($iv);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method setInitializationVector() does not exist on CryptoManana\Core\Interf...DataEncryptionInterface. It seems like you code against a sub-type of CryptoManana\Core\Interf...DataEncryptionInterface such as CryptoManana\Core\Abstra...actBlockCipherAlgorithm. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

167
        $this->symmetricCipherSource->setSecretKey($key)->/** @scrutinizer ignore-call */ setInitializationVector($iv);
Loading history...
168
169
        $cipherData = $this->symmetricCipherSource->encryptData($plainData);
170
        $key = $this->asymmetricCipherSource->encryptData($key);
2 ignored issues
show
Bug introduced by
The method encryptData() does not exist on CryptoManana\Core\Abstra...tricEncryptionAlgorithm. It seems like you code against a sub-type of CryptoManana\Core\Abstra...tricEncryptionAlgorithm such as CryptoManana\Core\Abstra...n\AbstractRsaEncryption. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

170
        /** @scrutinizer ignore-call */ 
171
        $key = $this->asymmetricCipherSource->encryptData($key);
Loading history...
Bug introduced by
The method encryptData() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

170
        /** @scrutinizer ignore-call */ 
171
        $key = $this->asymmetricCipherSource->encryptData($key);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
171
        $iv = $this->asymmetricCipherSource->encryptData($iv);
172
        $macTag = isset($this->keyedDigestionSource) ? $this->keyedDigestionSource->hashData($cipherData) : '';
1 ignored issue
show
Bug introduced by
The method hashData() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

172
        $macTag = isset($this->keyedDigestionSource) ? $this->keyedDigestionSource->/** @scrutinizer ignore-call */ hashData($cipherData) : '';

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
173
174
        return new EnvelopeStructure($key, $iv, $cipherData, $macTag);
175
    }
176
177
    /**
178
     * Opens the envelope and extracts secured information from it.
179
     *
180
     * @param EnvelopeStructure $envelopeData The sealed envelope object.
181
     *
182
     * @return string The plain message information.
183
     * @throws \Exception Validation errors.
184
     */
185
    public function openEnvelope(EnvelopeStructure $envelopeData)
186
    {
187
        $key = $this->asymmetricCipherSource->decryptData($envelopeData->key);
1 ignored issue
show
Bug introduced by
The method decryptData() does not exist on CryptoManana\Core\Abstra...tricEncryptionAlgorithm. It seems like you code against a sub-type of CryptoManana\Core\Abstra...tricEncryptionAlgorithm such as CryptoManana\Core\Abstra...n\AbstractRsaEncryption. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

187
        /** @scrutinizer ignore-call */ 
188
        $key = $this->asymmetricCipherSource->decryptData($envelopeData->key);
Loading history...
188
        $iv = $this->asymmetricCipherSource->decryptData($envelopeData->iv);
189
190
        $this->symmetricCipherSource->setSecretKey($key)->setInitializationVector($iv);
191
192
        if (isset($this->keyedDigestionSource) && isset($envelopeData->authenticationTag)) {
193
            if (!$this->keyedDigestionSource->verifyHash($envelopeData->cipherData, $envelopeData->authenticationTag)) {
194
                throw new \RuntimeException('Wrong MAC tag, the data has been tampered with or defected.');
195
            }
196
        }
197
198
        return $this->symmetricCipherSource->decryptData($envelopeData->cipherData);
199
    }
200
}
201