Issues (994)

src/Crypto/Cipher.php (7 issues)

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

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

64
      $length = openssl_cipher_iv_length($this->/** @scrutinizer ignore-call */ getOptions('method'));

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...
65
    } catch (Throwable $t) {
66
      throw new NotSecureIVGenerated('Unable to generate random IV.');
67
    }
68
69
    // For any reason if required IV size needs greater value.
70
    if ($length > strlen($allowedIVString)) {
71
      $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

71
      $repeatedIVString = str_repeat($allowedIVString, /** @scrutinizer ignore-type */ ceil($length / strlen($allowedIVString)));
Loading history...
72
      $allowedIVString .= $repeatedIVString;
73
    }
74
75
    return substr(str_shuffle($allowedIVString), 0, $length);
76
  }
77
78
  public function getComputedHash($key)
79
  {
80
    $hash = $key;
81
    for ($i = 0; $i < intval($this->getOptions('numberOfIterations')); ++$i) {
82
      $hash = hash($this->getOptions('algorithm'), $hash);
83
    }
84
85
    return $hash;
86
  }
87
88
  public function encrypt($plainText, $key, $initVector)
89
  {
90
    return $this->encryptOrDecrypt('encrypt', $plainText, $key, $initVector);
0 ignored issues
show
The method encryptOrDecrypt() does not exist on Crypto\Cipher. Did you maybe mean encrypt()? ( Ignorable by Annotation )

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

90
    return $this->/** @scrutinizer ignore-call */ encryptOrDecrypt('encrypt', $plainText, $key, $initVector);

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...
91
  }
92
93
  public function decrypt($encryptedText, $key, $initVector)
94
  {
95
    $plainText = $this->encryptOrDecrypt('decrypt', $encryptedText, $key, $initVector);
96
97
    if (false === $plainText) {
98
      throw new UnableToDecrypt('Unable to decrypt your encrypted string.');
99
    }
100
101
    return $plainText;
102
  }
103
104
  public function encryptPlainTextWithRandomIV($plainText, $key)
105
  {
106
    return $this->encryptOrDecrypt('encrypt', $this->generateRandomIV() . $plainText, $key, $this->generateRandomIV());
0 ignored issues
show
The method generateRandomIV() does not exist on Crypto\Cipher. ( Ignorable by Annotation )

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

106
    return $this->encryptOrDecrypt('encrypt', $this->/** @scrutinizer ignore-call */ generateRandomIV() . $plainText, $key, $this->generateRandomIV());

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...
107
  }
108
109
  public function decryptCipherTextWithRandomIV($cipherText, $key)
110
  {
111
    return substr(
112
      $this->encryptOrDecrypt('decrypt', $cipherText, $key, $this->generateRandomIV()),
113
      intval($this->getOptions('maxIVSize'))
114
    );
115
  }
116
117
  private function encryptOrDecrypt($mode, $string, $key, $initVector)
118
  {
119
    $password = substr($this->getComputedHash($key), 0, intval($this->getOptions('maxKeySize')));
0 ignored issues
show
The method getComputedHash() does not exist on Crypto\Cipher. ( Ignorable by Annotation )

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

119
    $password = substr($this->/** @scrutinizer ignore-call */ getComputedHash($key), 0, intval($this->getOptions('maxKeySize')));

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...
120
121
    if ('encrypt' === $mode) {
122
      return base64_encode(openssl_encrypt(
123
        $string,
124
        $this->getOptions('method'),
125
        $password,
126
        OPENSSL_RAW_DATA,
127
        $initVector
128
      ));
129
    }
130
131
    return openssl_decrypt(
132
      base64_decode($string),
133
      $this->getOptions('method'),
134
      $password,
135
      OPENSSL_RAW_DATA,
136
      $initVector
137
    );
138
  }
139
}
140