diff options
Diffstat (limited to 'vendor/aws/aws-sdk-php/src/Crypto/AesDecryptingStream.php')
-rw-r--r-- | vendor/aws/aws-sdk-php/src/Crypto/AesDecryptingStream.php | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/vendor/aws/aws-sdk-php/src/Crypto/AesDecryptingStream.php b/vendor/aws/aws-sdk-php/src/Crypto/AesDecryptingStream.php new file mode 100644 index 0000000..c1524cc --- /dev/null +++ b/vendor/aws/aws-sdk-php/src/Crypto/AesDecryptingStream.php @@ -0,0 +1,146 @@ +<?php +namespace Aws\Crypto; + +use GuzzleHttp\Psr7\StreamDecoratorTrait; +use \LogicException; +use Psr\Http\Message\StreamInterface; +use Aws\Crypto\Cipher\CipherMethod; + +/** + * @internal Represents a stream of data to be decrypted with passed cipher. + */ +class AesDecryptingStream implements AesStreamInterface +{ + const BLOCK_SIZE = 16; // 128 bits + + use StreamDecoratorTrait; + + /** + * @var string + */ + private $buffer = ''; + + /** + * @var CipherMethod + */ + private $cipherMethod; + + /** + * @var string + */ + private $key; + + /** + * @var StreamInterface + */ + private $stream; + + /** + * @param StreamInterface $cipherText + * @param string $key + * @param CipherMethod $cipherMethod + */ + public function __construct( + StreamInterface $cipherText, + $key, + CipherMethod $cipherMethod + ) { + $this->stream = $cipherText; + $this->key = $key; + $this->cipherMethod = clone $cipherMethod; + } + + public function getOpenSslName() + { + return $this->cipherMethod->getOpenSslName(); + } + + public function getAesName() + { + return $this->cipherMethod->getAesName(); + } + + public function getCurrentIv() + { + return $this->cipherMethod->getCurrentIv(); + } + + public function getSize() + { + $plainTextSize = $this->stream->getSize(); + + if ($this->cipherMethod->requiresPadding()) { + // PKCS7 padding requires that between 1 and self::BLOCK_SIZE be + // added to the plaintext to make it an even number of blocks. The + // plaintext is between strlen($cipherText) - self::BLOCK_SIZE and + // strlen($cipherText) - 1 + return null; + } + + return $plainTextSize; + } + + public function isWritable() + { + return false; + } + + public function read($length) + { + if ($length > strlen($this->buffer)) { + $this->buffer .= $this->decryptBlock( + (int) ( + self::BLOCK_SIZE * ceil(($length - strlen($this->buffer)) / self::BLOCK_SIZE) + ) + ); + } + + $data = substr($this->buffer, 0, $length); + $this->buffer = substr($this->buffer, $length); + + return $data ? $data : ''; + } + + public function seek($offset, $whence = SEEK_SET) + { + if ($offset === 0 && $whence === SEEK_SET) { + $this->buffer = ''; + $this->cipherMethod->seek(0, SEEK_SET); + $this->stream->seek(0, SEEK_SET); + } else { + throw new LogicException('AES encryption streams only support being' + . ' rewound, not arbitrary seeking.'); + } + } + + private function decryptBlock($length) + { + if ($this->stream->eof()) { + return ''; + } + + $cipherText = ''; + do { + $cipherText .= $this->stream->read((int) ($length - strlen($cipherText))); + } while (strlen($cipherText) < $length && !$this->stream->eof()); + + $options = OPENSSL_RAW_DATA; + if (!$this->stream->eof() + && $this->stream->getSize() !== $this->stream->tell() + ) { + $options |= OPENSSL_ZERO_PADDING; + } + + $plaintext = openssl_decrypt( + $cipherText, + $this->cipherMethod->getOpenSslName(), + $this->key, + $options, + $this->cipherMethod->getCurrentIv() + ); + + $this->cipherMethod->update($cipherText); + + return $plaintext; + } +} |