Issues (994)

src/CryptoLib/CryptoLib.php (5 issues)

Labels
Severity
1
<?php
2
3
namespace MrShan0\CryptoLib;
4
5
use MrShan0\CryptoLib\Exceptions\NotSecureIVGenerated;
6
use MrShan0\CryptoLib\Exceptions\UnableToDecrypt;
7
use Throwable;
8
9
class CryptoLib
10
{
11
    /**
12
     * Default setting for generating hash
13
     *
14
     * @var array
15
     */
16
    private $_opts = [
17
18
        /**
19
         * Crypto method to encrypt your string with
20
         */
21
        'method'             => 'AES-256-CBC',
22
23
        /**
24
         * Algorithm to apply while generating password via secrety key
25
         */
26
        'algorithm'          => 'sha256',
27
28
        /**
29
         * Maximum key size
30
         */
31
        'maxKeySize'         => 32,
32
33
        /**
34
         * Maximum IV size
35
         */
36
        'maxIVSize'          => 16,
37
38
        /**
39
         * Number of iterations to generate hash for password
40
         */
41
        'numberOfIterations' => 1,
42
    ];
43
44
    public function __construct(array $options = array())
45
    {
46
        $this->_opts = $options + $this->_opts;
47
    }
48
49
    public function getOptions($key = '')
50
    {
51
        if ($key) {
52
            return $this->_opts[$key];
53
        }
54
55
        return $this->_opts;
56
    }
57
58
    public function generateRandomIV()
59
    {
60
        // We need to generate our IV by following characters
61
        $allowedIVString = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_';
62
63
        try {
64
            // Invalid method will throw a warning.
65
            $length = openssl_cipher_iv_length($this->getOptions('method'));
0 ignored issues
show
It seems like $this->getOptions('method') can also be of type array; however, parameter $cipher_algo of openssl_cipher_iv_length() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

65
            $length = openssl_cipher_iv_length(/** @scrutinizer ignore-type */ $this->getOptions('method'));
Loading history...
66
        } catch (Throwable $t) {
67
            throw new NotSecureIVGenerated("Unable to generate random IV.");
68
        }
69
70
        // For any reason if required IV size needs greater value.
71
        if ($length > strlen($allowedIVString)) {
72
            $repeatedIVString = str_repeat($allowedIVString, ceil($length/strlen($allowedIVString)));
0 ignored issues
show
ceil($length / strlen($allowedIVString)) of type double is incompatible with the type integer expected by parameter $times of str_repeat(). ( Ignorable by Annotation )

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

72
            $repeatedIVString = str_repeat($allowedIVString, /** @scrutinizer ignore-type */ ceil($length/strlen($allowedIVString)));
Loading history...
73
            $allowedIVString .= $repeatedIVString;
74
        }
75
76
        return substr(str_shuffle($allowedIVString), 0, $length);
77
    }
78
79
    public function getComputedHash($key)
80
    {
81
        $hash = $key;
82
        for ($i = 0; $i < intval($this->getOptions('numberOfIterations')); $i++) {
83
            $hash = hash($this->getOptions('algorithm'), $hash);
0 ignored issues
show
It seems like $this->getOptions('algorithm') can also be of type array; however, parameter $algo of hash() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

83
            $hash = hash(/** @scrutinizer ignore-type */ $this->getOptions('algorithm'), $hash);
Loading history...
84
        }
85
86
        return $hash;
87
    }
88
89
    public function encrypt($plainText, $key, $initVector)
90
    {
91
        return $this->encryptOrDecrypt('encrypt', $plainText, $key, $initVector);
92
    }
93
94
    public function decrypt($encryptedText, $key, $initVector)
95
    {
96
        $plainText = $this->encryptOrDecrypt('decrypt', $encryptedText, $key, $initVector);
97
98
        if (false === $plainText) {
99
            throw new UnableToDecrypt('Unable to decrypt your encrypted string.');
100
        }
101
102
        return $plainText;
103
    }
104
105
    public function encryptPlainTextWithRandomIV($plainText, $key)
106
    {
107
        return $this->encryptOrDecrypt('encrypt', $this->generateRandomIV() . $plainText, $key, $this->generateRandomIV());
108
    }
109
110
    public function decryptCipherTextWithRandomIV($cipherText, $key)
111
    {
112
        return substr(
113
            $this->encryptOrDecrypt('decrypt', $cipherText, $key, $this->generateRandomIV()),
114
            intval($this->getOptions('maxIVSize'))
115
        );
116
    }
117
118
    private function encryptOrDecrypt($mode, $string, $key, $initVector)
119
    {
120
        $password = substr($this->getComputedHash($key), 0, intval($this->getOptions('maxKeySize')));
121
122
        if ('encrypt' === $mode) {
123
            return base64_encode(openssl_encrypt(
124
                $string,
125
                $this->getOptions('method'),
0 ignored issues
show
It seems like $this->getOptions('method') can also be of type array; however, parameter $cipher_algo of openssl_encrypt() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

125
                /** @scrutinizer ignore-type */ $this->getOptions('method'),
Loading history...
126
                $password,
127
                OPENSSL_RAW_DATA,
128
                $initVector
129
            ));
130
        }
131
132
        return openssl_decrypt(
133
            base64_decode($string),
134
            $this->getOptions('method'),
0 ignored issues
show
It seems like $this->getOptions('method') can also be of type array; however, parameter $cipher_algo of openssl_decrypt() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

134
            /** @scrutinizer ignore-type */ $this->getOptions('method'),
Loading history...
135
            $password,
136
            OPENSSL_RAW_DATA,
137
            $initVector
138
        );
139
    }
140
141
}
142