Completed
Push — master ( 98068e...4222c9 )
by Tony Karavasilev (Тони
19:09
created

fetchAlgorithmMethodName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
ccs 0
cts 3
cp 0
rs 10
cc 1
nc 1
nop 0
crap 2
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
    protected function fetchAlgorithmMethodName()
47
    {
48
        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
    protected function validatePlainDataForEncryption($plainData)
59
    {
60
        if (!is_string($plainData)) {
61
            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
    protected function validateCipherDataForDecryption($cipherData)
73
    {
74
        if (!is_string($cipherData)) {
75
            throw new \InvalidArgumentException('The data for decryption must be a string or a binary string.');
76
        } elseif ($cipherData === '') {
77
            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
    public function __construct()
85
    {
86
        /**
87
         * {@internal Serialization and initialization purposes for the default key. }}
88
         */
89
        if (strlen($this->key) < static::KEY_SIZE) {
90
            $this->key = str_pad($this->key, static::KEY_SIZE, "\x0", STR_PAD_RIGHT);
91
        }
92
93
        // @codeCoverageIgnoreStart
94
        if (!in_array($this->fetchAlgorithmMethodName(), openssl_get_cipher_methods(), true)) {
95
            throw new \RuntimeException(
96
                'The algorithm `' .
97
                $this->fetchAlgorithmMethodName() .
98
                '`is not supported under the current system configuration.'
99
            );
100
        }
101
        // @codeCoverageIgnoreEnd
102
    }
103
104
    /**
105
     * Encrypts the given plain data.
106
     *
107
     * @param string $plainData The plain input string.
108
     *
109
     * @return string The cipher/encrypted data.
110
     * @throws \Exception Validation errors.
111
     */
112
    public function encryptData($plainData)
113
    {
114
        $this->validatePlainDataForEncryption($plainData);
115
116
        $plainData = ($plainData === '') ? ' ' : $plainData;
117
118
        $cipherData = openssl_encrypt($plainData, $this->fetchAlgorithmMethodName(), $this->key, OPENSSL_RAW_DATA, '');
119
120
        return $this->changeOutputFormat($cipherData, true);
121
    }
122
123
    /**
124
     * Decrypts the given cipher data.
125
     *
126
     * @param string $cipherData The encrypted input string.
127
     *
128
     * @return string The decrypted/plain data.
129
     * @throws \Exception Validation errors.
130
     */
131
    public function decryptData($cipherData)
132
    {
133
        $this->validateCipherDataForDecryption($cipherData);
134
135
        $cipherData = $this->changeOutputFormat($cipherData, false);
136
137
        $plainData = openssl_decrypt($cipherData, $this->fetchAlgorithmMethodName(), $this->key, OPENSSL_RAW_DATA, '');
138
139
        return ($plainData === false) ? '' : $plainData;
140
    }
141
142
    /**
143
     * Get debug information for the class instance.
144
     *
145
     * @return array Debug information.
146
     */
147
    public function __debugInfo()
148
    {
149
        return [
150
            'standard' => static::ALGORITHM_NAME,
151
            'type' => 'symmetrical encryption or two-way stream cipher',
152
            'key size in bits' => static::KEY_SIZE * 8,
153
            'secret key' => $this->key,
154
            'internal algorithm full name' => $this->fetchAlgorithmMethodName(),
155
            'internal long data digestion algorithm' => 'HKDF-SHA-2-128',
156
        ];
157
    }
158
}
159