File ManagerCurrent Directory: wp-content/plugins/backwpup/src/Infrastructure/SecurityLinux appserver-0d5e4f1e-php-cc8da225320a42ba9b7d66cba40b1f03 6.6.123+ #1 SMP PREEMPT_DYNAMIC Wed Mar 11 09:04:28 UTC 2026 x86_64Edit File: EncryptionStream.php <?php declare(strict_types=1); namespace Inpsyde\BackWPup\Infrastructure\Security; use GuzzleHttp\Psr7\StreamDecoratorTrait; use phpseclib3\Crypt\AES; use phpseclib3\Crypt\PublicKeyLoader; use phpseclib3\Crypt\RSA; use Psr\Http\Message\StreamInterface; final class EncryptionStream implements StreamInterface { use StreamDecoratorTrait; public const TYPE_SYMMETRIC = 1; public const TYPE_ASYMMETRIC = 2; private const HEADER = "\x42\x41\x43\x4b\x57\x50\x55\x50"; private const VERSION = 2; private const BLOCK_SIZE = 16; /** * @var AES */ private $aesEncryptor; /** * @var RSA\PublicKey|null */ private $rsaEncryptor; /** * @var self::TYPE_* */ private $type; /** * @var string */ private $aesIv; /** * @var string */ private $key; /** * @var StreamInterface */ private $stream; /** * @psalm-param self::TYPE_* $type * * @throws \RuntimeException If the IV cannot be generated */ public function __construct(string $aesIv, string $key, StreamInterface $output, string $rsaPubKey = '') { $this->type = self::TYPE_SYMMETRIC; if ($rsaPubKey) { $this->type = self::TYPE_ASYMMETRIC; } if (!$aesIv && strlen($aesIv) !== 16) { throw new \InvalidArgumentException('Expected an IV with 16 chars for AES encryption'); } $this->aesIv = $aesIv; $this->stream = $output; $this->aesEncryptor = new AES('CBC'); $this->aesEncryptor->enableContinuousBuffer(); $this->aesEncryptor->disablePadding(); $this->aesEncryptor->setIV($this->aesIv); if (!$key && strlen($key) !== 32) { throw new \InvalidArgumentException('Expected an Key with min. 32 chars for AES encryption '); } $this->key = $key; $this->aesEncryptor->setKey($this->key); if ($rsaPubKey) { $rsa = PublicKeyLoader::load($rsaPubKey); if (!($rsa instanceof RSA\PublicKey)) { throw new \InvalidArgumentException('Expected an RSA public key'); } $this->rsaEncryptor = $rsa; } } /** * Encrypts and then writes the provided string. * * The string is AES-encrypted, either using the provided key * (see {@see EncryptionStream::fromSymmetric()}), or a key generated and * RSA-encrypted on initialization (see {@see EncryptionStream::fromAsymmetric()}). * * If this is the first data being written, then the encryption header is written first * (see {@see EncryptionStream::writeHeader()}). * * Each block of data is padded to the block size (16 bytes) as necessary, using PKCS7 padding. * * Note that if a block is an exact multiple of 16 bytes, 16 additional bytes of padding will be added. * * @param string $string The string to encrypt and write * * @return int The number of bytes written */ public function write($string): int { $bytes = $this->writeHeader(); $bytes += $this->stream->write($this->aesEncryptor->encrypt(self::addPadding($string))); return $bytes; } /** * Write the header of the encrypted message. * * If AES-encrypted, then the format is: * * * 8 byte header (0x4241434b57505550). * * 1 byte version (\x02). This is for the new format, supporting a custom IV. * The old format only supported a null IV. * * 1 byte type (\x01). This specifies symmetric key encryption. * * 16 bytes containing the clear-text IV. * * If RSA-encrypted, then the format is: * * * 8 byte header (0x4241434b57505550). * * 1 byte version (\x02). This is for the new format, supporting a custom IV * and larger RSA keys. The old format only supported a null IV and RSA keys * of less than 2048-bits. * * 1 byte type (\x02). This specifies asymmetric key encryption. * * 2 byte encoded key length (length in bytes, not bits). * * AES key encrypted with the given RSA public key. Key length must be equal to * number in the encoded length. * * 16 bytes containing the clear-text IV. * * @throws \RuntimeException If the header cannot be written * * @return int The number of bytes written in the header (0 if header already written) */ private function writeHeader(): int { if ($this->tell() !== 0) { return 0; } $prefix = self::HEADER . \chr(self::VERSION) . \chr($this->type); if ($this->type === self::TYPE_SYMMETRIC) { return $this->stream->write($prefix . $this->aesIv); } if ($this->rsaEncryptor === null) { throw new \RuntimeException('RSA encrypter not set'); } $this->aesEncryptor->setKey($this->key); $encryptedKey = $this->rsaEncryptor->encrypt($this->key); if (!\is_string($encryptedKey)) { throw new \RuntimeException('Could not encrypt key'); } return $this->stream->write( $prefix . pack('n', \strlen($encryptedKey)) . $encryptedKey . $this->aesIv ); } /** * Add PKCS7-style padding. */ private static function addPadding(string $string): string { $length = \strlen($string); $paddingNeeded = $length % 16; if ($paddingNeeded > 0) { $pad = 16 - ($paddingNeeded); $string = str_pad($string, $length + $pad, \chr($pad)); } return $string; } } Upload File Directory Listing NameTypeSizeActions.. (Parent Directory)DirEncryptionStream.phpFile5.52 KB Rename | Delete | Edit