aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/phpseclib/phpseclib2_compat/src/Crypt/Base.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/phpseclib/phpseclib2_compat/src/Crypt/Base.php')
-rw-r--r--vendor/phpseclib/phpseclib2_compat/src/Crypt/Base.php585
1 files changed, 585 insertions, 0 deletions
diff --git a/vendor/phpseclib/phpseclib2_compat/src/Crypt/Base.php b/vendor/phpseclib/phpseclib2_compat/src/Crypt/Base.php
new file mode 100644
index 000000000..fad69c023
--- /dev/null
+++ b/vendor/phpseclib/phpseclib2_compat/src/Crypt/Base.php
@@ -0,0 +1,585 @@
+<?php
+
+/**
+ * Base Class for all \phpseclib\Crypt\* cipher classes
+ *
+ * PHP version 5
+ *
+ * @category Crypt
+ * @package Base
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @author Hans-Juergen Petrich <petrich@tronic-media.com>
+ * @copyright 2007 Jim Wigginton
+ * @license http://www.opensource.org/licenses/mit-license.html MIT License
+ * @link http://phpseclib.sourceforge.net
+ */
+
+namespace phpseclib\Crypt;
+
+use phpseclib3\Exception\BadDecryptionException;
+use phpseclib3\Exception\InconsistentSetupException;
+
+/**
+ * Base Class for all \phpseclib\Crypt\* cipher classes
+ *
+ * @package Base
+ * @author Jim Wigginton <terrafrost@php.net>
+ * @author Hans-Juergen Petrich <petrich@tronic-media.com>
+ */
+abstract class Base
+{
+ /**#@+
+ * @access public
+ * @see \phpseclib\Crypt\Base::encrypt()
+ * @see \phpseclib\Crypt\Base::decrypt()
+ */
+ /**
+ * Encrypt / decrypt using the Counter mode.
+ *
+ * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
+ *
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
+ */
+ const MODE_CTR = -1;
+ /**
+ * Encrypt / decrypt using the Electronic Code Book mode.
+ *
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
+ */
+ const MODE_ECB = 1;
+ /**
+ * Encrypt / decrypt using the Code Book Chaining mode.
+ *
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
+ */
+ const MODE_CBC = 2;
+ /**
+ * Encrypt / decrypt using the Cipher Feedback mode.
+ *
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
+ */
+ const MODE_CFB = 3;
+ /**
+ * Encrypt / decrypt using the Cipher Feedback mode (8bit)
+ */
+ const MODE_CFB8 = 38;
+ /**
+ * Encrypt / decrypt using the Output Feedback mode (8bit)
+ */
+ const MODE_OFB8 = 7;
+ /**
+ * Encrypt / decrypt using the Output Feedback mode.
+ *
+ * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
+ */
+ const MODE_OFB = 4;
+ /**
+ * Encrypt / decrypt using streaming mode.
+ */
+ const MODE_STREAM = 5;
+ /**
+ * Encrypt / decrypt using Galois/Counter mode.
+ *
+ * @link https://en.wikipedia.org/wiki/Galois/Counter_Mode
+ */
+ const MODE_GCM = 6;
+ /**#@-*/
+
+ /**#@+
+ * @access private
+ * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
+ */
+ /**
+ * Base value for the internal implementation $engine switch
+ */
+ const ENGINE_INTERNAL = 1;
+ /**
+ * Base value for the eval() implementation $engine switch
+ */
+ const ENGINE_EVAL = 4;
+ /**
+ * Base value for the mcrypt implementation $engine switch
+ */
+ const ENGINE_MCRYPT = 2;
+ /**
+ * Base value for the openssl implementation $engine switch
+ */
+ const ENGINE_OPENSSL = 3;
+ /**
+ * Base value for the libsodium implementation $engine switch
+ */
+ const ENGINE_LIBSODIUM = 5;
+ /**
+ * Base value for the openssl / gcm implementation $engine switch
+ */
+ const ENGINE_OPENSSL_GCM = 6;
+ /**#@-*/
+
+ /**
+ * Engine Map
+ *
+ * @access private
+ * @see \phpseclib3\Crypt\Common\SymmetricKey::getEngine()
+ */
+ const ENGINE_MAP = [
+ self::ENGINE_INTERNAL => 'PHP',
+ self::ENGINE_EVAL => 'Eval',
+ self::ENGINE_MCRYPT => 'mcrypt',
+ self::ENGINE_OPENSSL => 'OpenSSL',
+ self::ENGINE_LIBSODIUM => 'libsodium',
+ self::ENGINE_OPENSSL_GCM => 'OpenSSL (GCM)'
+ ];
+
+ /**
+ * The Cipher
+ *
+ * @var \phpseclib3\Crypt\Common\SymmetricKey
+ * @access private
+ */
+ protected $cipher;
+
+ /**
+ * The Key
+ *
+ * @see self::setKey()
+ * @var string
+ * @access private
+ */
+ protected $key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+
+ /**
+ * Password Parameters
+ *
+ * @see self::setPassword()
+ * @var array
+ * @access private
+ */
+ protected $password = [];
+
+ /**
+ * The Key Length (in bytes)
+ *
+ * @see self::setKeyLength()
+ * @var int
+ * @access private
+ */
+ protected $key_length = 128;
+
+ /**
+ * Does internal cipher state need to be (re)initialized?
+ *
+ * @see self::setKey()
+ * @var bool
+ * @access private
+ */
+ private $changed = true;
+
+ /**
+ * Has the IV been set?
+ *
+ * @var bool
+ * @access private
+ */
+ protected $ivSet = false;
+
+ /**
+ * Has the key length been explictly set?
+ *
+ * @var bool
+ * @access private
+ */
+ protected $explicit_key_length = false;
+
+ /**
+ * Default Constructor.
+ *
+ * Determines whether or not the mcrypt extension should be used.
+ *
+ * $mode could be:
+ *
+ * - self::MODE_ECB
+ *
+ * - self::MODE_CBC
+ *
+ * - self::MODE_CTR
+ *
+ * - self::MODE_CFB
+ *
+ * - self::MODE_OFB
+ *
+ * If not explicitly set, self::MODE_CBC will be used.
+ *
+ * @param int $mode
+ * @access public
+ */
+ public function __construct($mode = self::MODE_CBC)
+ {
+ $map = [
+ self::MODE_CTR => 'ctr',
+ self::MODE_ECB => 'ecb',
+ self::MODE_CBC => 'cbc',
+ self::MODE_CFB => 'cfb',
+ self::MODE_CFB8 => 'cfb8',
+ self::MODE_OFB => 'ofb',
+ self::MODE_OFB8 => 'ofb8',
+ self::MODE_GCM => 'gcm',
+ self::MODE_STREAM => 'stream'
+ ];
+ if (!isset($map[$mode])) {
+ $mode = self::MODE_CBC;
+ }
+ $class = new \ReflectionClass(static::class);
+ $class = "phpseclib3\\Crypt\\" . $class->getShortName();
+ $this->cipher = new $class($map[$mode]);
+ $this->key_length = $this->cipher->getKeyLength();
+ }
+
+ /**
+ * Sets the initialization vector. (optional)
+ *
+ * SetIV is not required when self::MODE_ECB (or ie for AES: \phpseclib\Crypt\AES::MODE_ECB) is being used. If not explicitly set, it'll be assumed
+ * to be all zero's.
+ *
+ * @access public
+ * @param string $iv
+ * @internal Can be overwritten by a sub class, but does not have to be
+ */
+ public function setIV($iv)
+ {
+ $this->ivSet = true;
+
+ if (!$this->cipher->usesIV()) {
+ return;
+ }
+
+ $length = $this->cipher->getBlockLengthInBytes();
+ $iv = str_pad(substr($iv, 0, $length), $length, "\0");
+
+ try {
+ $this->cipher->setIV($iv);
+ } catch (\Exception $e) {}
+ }
+
+ /**
+ * Sets the key length.
+ *
+ * Keys with explicitly set lengths need to be treated accordingly
+ *
+ * @access public
+ * @param int $length
+ */
+ public function setKeyLength($length)
+ {
+ // algorithms that have a fixed key length should override this with a method that does nothing
+ $this->changed = true;
+ $this->key_length = static::calculateNewKeyLength($length);
+ $this->explicit_key_length = true;
+ }
+
+ /**
+ * Returns the current key length in bits
+ *
+ * @access public
+ * @return int
+ */
+ public function getKeyLength()
+ {
+ return $this->key_length;
+ }
+
+ /**
+ * Returns the current block length in bits
+ *
+ * @access public
+ * @return int
+ */
+ public function getBlockLength()
+ {
+ return $this->cipher->getBlockLength();
+ }
+
+ /**
+ * Sets the key.
+ *
+ * The min/max length(s) of the key depends on the cipher which is used.
+ * If the key not fits the length(s) of the cipher it will paded with null bytes
+ * up to the closest valid key length. If the key is more than max length,
+ * we trim the excess bits.
+ *
+ * If the key is not explicitly set, it'll be assumed to be all null bytes.
+ *
+ * @access public
+ * @param string $key
+ * @internal Could, but not must, extend by the child Crypt_* class
+ */
+ public function setKey($key)
+ {
+ $this->key = $key;
+ $this->password = [];
+ if (!$this->explicit_key_length) {
+ $this->key_length = static::calculateNewKeyLength(strlen($key) << 3);
+ }
+ $this->changed = true;
+ }
+
+ /**
+ * Sets the password.
+ *
+ * Depending on what $method is set to, setPassword()'s (optional) parameters are as follows:
+ * {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2} or pbkdf1:
+ * $hash, $salt, $count, $dkLen
+ *
+ * Where $hash (default = sha1) currently supports the following hashes: see: Crypt/Hash.php
+ *
+ * @see Crypt/Hash.php
+ * @param string $password
+ * @param string $method
+ * @return bool
+ * @access public
+ * @internal Could, but not must, extend by the child Crypt_* class
+ */
+ public function setPassword($password, $method = 'pbkdf2')
+ {
+ $this->password = func_get_args();
+ $this->cipher->setKeyLength($this->key_length);
+ $this->cipher->setPassword(...func_get_args());
+ }
+
+ /**
+ * Encrypts a message.
+ *
+ * $plaintext will be padded with additional bytes such that it's length is a multiple of the block size. Other cipher
+ * implementations may or may not pad in the same manner. Other common approaches to padding and the reasons why it's
+ * necessary are discussed in the following
+ * URL:
+ *
+ * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
+ *
+ * An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does.
+ * strlen($plaintext) will still need to be a multiple of the block size, however, arbitrary values can be added to make it that
+ * length.
+ *
+ * @see self::decrypt()
+ * @access public
+ * @param string $plaintext
+ * @return string $ciphertext
+ * @internal Could, but not must, extend by the child Crypt_* class
+ */
+ public function encrypt($plaintext)
+ {
+ if ($this->changed) {
+ $this->setup();
+ }
+
+ try {
+ return $this->cipher->encrypt($plaintext);
+ } catch (\LengthException $e) {
+ user_error($e->getMessage());
+ $this->cipher->enablePadding();
+ return $this->cipher->encrypt($plaintext);
+ }
+ }
+
+ /**
+ * Decrypts a message.
+ *
+ * If strlen($ciphertext) is not a multiple of the block size, null bytes will be added to the end of the string until
+ * it is.
+ *
+ * @see self::encrypt()
+ * @access public
+ * @param string $ciphertext
+ * @return string $plaintext
+ * @internal Could, but not must, extend by the child Crypt_* class
+ */
+ public function decrypt($ciphertext)
+ {
+ if ($this->changed) {
+ $this->setup();
+ }
+
+ try {
+ return $this->cipher->decrypt($ciphertext);
+ } catch (\LengthException $e) {
+ $len = strlen($ciphertext);
+ $block_size = $this->cipher->getBlockLengthInBytes();
+ $ciphertext = str_pad($ciphertext, $len + ($block_size - $len % $block_size) % $block_size, chr(0));
+ try {
+ return $this->cipher->decrypt($ciphertext);
+ } catch (BadDecryptionException $e) {
+ return false;
+ }
+ } catch (\Exception $e) {
+ return false;
+ }
+ }
+
+ /**
+ * Setup IV and key
+ */
+ protected function setup()
+ {
+ // we set this just in case it was already set to anything via setPassword()
+ $temp = $this->explicit_key_length;
+ $this->setKeyLength($this->key_length);
+ $this->explicit_key_length = $temp;
+ if ($this->explicit_key_length) {
+ $this->cipher->setKeyLength($this->key_length);
+ }
+ if (empty($this->password)) {
+ $key_length = $this->key_length >> 3;
+ $key = str_pad(substr($this->key, 0, $key_length), $key_length, "\0");
+ $this->cipher->setKey($key);
+ } else {
+ $this->cipher->setPassword(...$this->password);
+ }
+ if (!$this->ivSet) {
+ $this->setIV('');
+ }
+ $this->changed = false;
+ }
+
+ /**
+ * Pad "packets".
+ *
+ * Block ciphers working by encrypting between their specified [$this->]block_size at a time
+ * If you ever need to encrypt or decrypt something that isn't of the proper length, it becomes necessary to
+ * pad the input so that it is of the proper length.
+ *
+ * Padding is enabled by default. Sometimes, however, it is undesirable to pad strings. Such is the case in SSH,
+ * where "packets" are padded with random bytes before being encrypted. Unpad these packets and you risk stripping
+ * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
+ * transmitted separately)
+ *
+ * @see self::disablePadding()
+ * @access public
+ */
+ public function enablePadding()
+ {
+ $this->cipher->enablePadding();
+ }
+
+ /**
+ * Do not pad packets.
+ *
+ * @see self::enablePadding()
+ * @access public
+ */
+ public function disablePadding()
+ {
+ $this->cipher->disablePadding();
+ }
+
+ /**
+ * Treat consecutive "packets" as if they are a continuous buffer.
+ *
+ * Say you have a 32-byte plaintext $plaintext. Using the default behavior, the two following code snippets
+ * will yield different outputs:
+ *
+ * <code>
+ * echo $rijndael->encrypt(substr($plaintext, 0, 16));
+ * echo $rijndael->encrypt(substr($plaintext, 16, 16));
+ * </code>
+ * <code>
+ * echo $rijndael->encrypt($plaintext);
+ * </code>
+ *
+ * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
+ * another, as demonstrated with the following:
+ *
+ * <code>
+ * $rijndael->encrypt(substr($plaintext, 0, 16));
+ * echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
+ * </code>
+ * <code>
+ * echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
+ * </code>
+ *
+ * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
+ * outputs. The reason is due to the fact that the initialization vector's change after every encryption /
+ * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
+ *
+ * Put another way, when the continuous buffer is enabled, the state of the \phpseclib\Crypt\*() object changes after each
+ * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
+ * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
+ * however, they are also less intuitive and more likely to cause you problems.
+ *
+ * @see self::disableContinuousBuffer()
+ * @access public
+ * @internal Could, but not must, extend by the child Crypt_* class
+ */
+ public function enableContinuousBuffer()
+ {
+ try {
+ $this->cipher->enableContinuousBuffer();
+ } catch (\BadMethodCallException $e) {
+ user_error($e->getMessage());
+ }
+ }
+
+ /**
+ * Treat consecutive packets as if they are a discontinuous buffer.
+ *
+ * The default behavior.
+ *
+ * @see self::enableContinuousBuffer()
+ * @access public
+ * @internal Could, but not must, extend by the child Crypt_* class
+ */
+ public function disableContinuousBuffer()
+ {
+ $this->cipher->disableContinuousBuffer();
+ }
+
+ /**
+ * Test for engine validity
+ *
+ * @see self::__construct()
+ * @param int $engine
+ * @access public
+ * @return bool
+ */
+ public function isValidEngine($engine)
+ {
+ $map = self::ENGINE_MAP;
+ return $this->cipher->isValidEngine($map[$engine]);
+ }
+
+ /**
+ * Sets the preferred crypt engine
+ *
+ * Currently, $engine could be:
+ *
+ * - \phpseclib\Crypt\Base::ENGINE_OPENSSL [very fast]
+ *
+ * - \phpseclib\Crypt\Base::ENGINE_MCRYPT [fast]
+ *
+ * - \phpseclib\Crypt\Base::ENGINE_INTERNAL [slow]
+ *
+ * If the preferred crypt engine is not available the fastest available one will be used
+ *
+ * @see self::__construct()
+ * @param int $engine
+ * @access public
+ */
+ public function setPreferredEngine($engine)
+ {
+ $map = self::ENGINE_MAP;
+ $this->cipher->setPreferredEngine($map[$engine]);
+ }
+
+ /**
+ * Returns the engine currently being utilized
+ *
+ * @see self::_setEngine()
+ * @access public
+ */
+ public function getEngine()
+ {
+ static $reverseMap;
+ if (!isset($reverseMap)) {
+ $reverseMap = array_flip(self::ENGINE_MAP);
+ }
+ return $reverseMap[$this->cipher->getEngine()];
+ }
+} \ No newline at end of file