Passed
Branch staging (dcaea3)
by Tony Karavasilev (Тони
02:31
created

AbstractStreamCipherAlgorithm::decryptData()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 4
c 1
b 0
f 0
dl 0
loc 9
ccs 0
cts 0
cp 0
rs 10
cc 2
nc 2
nop 1
crap 6
1
<?php
2
3
/**
4
 * The symmetric stream cipher encryption algorithm abstraction specification.
5
 */
6
7
namespace CryptoManana\Core\Abstractions\MessageEncryption;
8
9
use CryptoManana\Core\Abstractions\MessageEncryption\AbstractSymmetricEncryptionAlgorithm as SymmetricCipherAlgorithm;
10
use CryptoManana\Core\Interfaces\MessageEncryption\ObjectEncryptionInterface as ObjectEncryption;
11
use CryptoManana\Core\Interfaces\MessageEncryption\FileEncryptionInterface as FileEncryption;
12
use CryptoManana\Core\Traits\MessageEncryption\ObjectEncryptionTrait as EncryptObjects;
13
use CryptoManana\Core\Traits\MessageEncryption\FileEncryptionTrait as EncryptFiles;
14
15
/**
16
 * Class AbstractStreamCipherAlgorithm - The symmetric stream cipher algorithm abstraction representation.
17
 *
18
 * @package CryptoManana\Core\Abstractions\MessageEncryption
19
 *
20
 * @mixin EncryptObjects
21
 * @mixin EncryptFiles
22
 */
23
abstract class AbstractStreamCipherAlgorithm extends SymmetricCipherAlgorithm implements
24
    ObjectEncryption,
25
    FileEncryption
26
{
27
    /**
28
     * Object encryption and decryption capabilities.
29
     *
30
     * {@internal Reusable implementation of `ObjectEncryptionInterface`. }}
31
     */
32
    use EncryptObjects;
33
34
    /**
35
     * File content encryption and decryption capabilities.
36
     *
37
     * {@internal Reusable implementation of `FileEncryptionInterface`. }}
38
     */
39
    use EncryptFiles;
40
41
    /**
42
     * Fetch the correctly formatted internal encryption algorithm method name.
43
     *
44
     * @return string The symmetric encryption algorithm standard.
45
     */
46 50
    protected function fetchAlgorithmMethodName()
47
    {
48 50
        return static::ALGORITHM_NAME;
49
    }
50
51
    /**
52
     * Internal method for the validation of plain data used at encryption operations.
53
     *
54
     * @param string $plainData The plain input string.
55
     *
56
     * @throws \Exception Validation errors.
57
     */
58 22
    protected function validatePlainDataForEncryption($plainData)
59
    {
60 22
        if (!is_string($plainData)) {
61 2
            throw new \InvalidArgumentException('The data for encryption must be a string or a binary string.');
62
        }
63
    }
64
65
    /**
66
     * Internal method for the validation of cipher data used at decryption operations.
67
     *
68
     * @param string $cipherData The encrypted input string.
69
     *
70
     * @throws \Exception Validation errors.
71
     */
72 18
    protected function validateCipherDataForDecryption($cipherData)
73
    {
74 18
        if (!is_string($cipherData)) {
75 2
            throw new \InvalidArgumentException('The data for decryption must be a string or a binary string.');
76 16
        } elseif ($cipherData === '') {
77 2
            throw new \InvalidArgumentException('The string is empty and there is nothing to decrypt from it.');
78
        }
79
    }
80
81
    /**
82
     * Stream cipher algorithm constructor.
83
     *
84
     * @codeCoverageIgnore
85
     */
86
    public function __construct()
87
    {
88
        /**
89
         * {@internal Serialization and initialization purposes for the default key. }}
90
         */
91
        if (strlen($this->key) < static::KEY_SIZE) {
92
            $this->key = str_pad($this->key, static::KEY_SIZE, "\x0", STR_PAD_RIGHT);
93
        }
94
95
        if (!in_array(strtolower($this->fetchAlgorithmMethodName()), openssl_get_cipher_methods(), true)) {
96
            throw new \RuntimeException(
97
                'The algorithm `' .
98
                $this->fetchAlgorithmMethodName() .
99
                '`is not supported under the current system configuration.'
100
            );
101
        }
102
    }
103
104
    /**
105
     * Get debug information for the class instance.
106
     *
107
     * @return array Debug information.
108
     */
109 2
    public function __debugInfo()
110
    {
111 2
        return [
112 2
            'standard' => static::ALGORITHM_NAME,
113 2
            'type' => 'symmetrical encryption or two-way stream cipher',
114 2
            'key size in bits' => static::KEY_SIZE * 8,
115 2
            'secret key' => $this->key,
116 2
            'internal algorithm full name' => $this->fetchAlgorithmMethodName(),
117 2
            'internal long data digestion algorithm' => 'HKDF-SHA-2-128',
118 2
        ];
119
    }
120
121
    /**
122
     * Encrypts the given plain data.
123
     *
124
     * @param string $plainData The plain input string.
125
     *
126
     * @return string The cipher/encrypted data.
127
     * @throws \Exception Validation errors.
128
     *
129
     * @codeCoverageIgnore
130
     */
131
    public function encryptData($plainData)
132
    {
133
        $this->validatePlainDataForEncryption($plainData);
134
135
        $plainData = ($plainData === '') ? ' ' : $plainData;
136
137
        $cipherData = openssl_encrypt($plainData, $this->fetchAlgorithmMethodName(), $this->key, OPENSSL_RAW_DATA, '');
138
139
        return $this->changeOutputFormat($cipherData, true);
140
    }
141
142
    /**
143
     * Decrypts the given cipher data.
144
     *
145
     * @param string $cipherData The encrypted input string.
146
     *
147
     * @return string The decrypted/plain data.
148
     * @throws \Exception Validation errors.
149
     *
150
     * @codeCoverageIgnore
151
     */
152
    public function decryptData($cipherData)
153
    {
154
        $this->validateCipherDataForDecryption($cipherData);
155
156
        $cipherData = $this->changeOutputFormat($cipherData, false);
157
158
        $plainData = openssl_decrypt($cipherData, $this->fetchAlgorithmMethodName(), $this->key, OPENSSL_RAW_DATA, '');
159
160
        return ($plainData === false) ? '' : $plainData;
161
    }
162
}
163