Cipher
11 months ago
Polyfill
11 months ago
AbstractCryptoClient.php
11 months ago
AbstractCryptoClientV2.php
11 months ago
AesDecryptingStream.php
11 months ago
AesEncryptingStream.php
11 months ago
AesGcmDecryptingStream.php
11 months ago
AesGcmEncryptingStream.php
11 months ago
AesStreamInterface.php
11 months ago
AesStreamInterfaceV2.php
11 months ago
DecryptionTrait.php
11 months ago
DecryptionTraitV2.php
11 months ago
EncryptionTrait.php
11 months ago
EncryptionTraitV2.php
11 months ago
KmsMaterialsProvider.php
11 months ago
KmsMaterialsProviderV2.php
11 months ago
MaterialsProvider.php
11 months ago
MaterialsProviderInterface.php
11 months ago
MaterialsProviderInterfaceV2.php
11 months ago
MaterialsProviderV2.php
11 months ago
MetadataEnvelope.php
11 months ago
MetadataStrategyInterface.php
11 months ago
AesEncryptingStream.php
152 lines
| 1 | <?php |
| 2 | namespace Aws\Crypto; |
| 3 | |
| 4 | use GuzzleHttp\Psr7\StreamDecoratorTrait; |
| 5 | use \LogicException; |
| 6 | use Psr\Http\Message\StreamInterface; |
| 7 | use Aws\Crypto\Cipher\CipherMethod; |
| 8 | |
| 9 | /** |
| 10 | * @internal Represents a stream of data to be encrypted with a passed cipher. |
| 11 | */ |
| 12 | class AesEncryptingStream implements AesStreamInterface |
| 13 | { |
| 14 | const BLOCK_SIZE = 16; // 128 bits |
| 15 | |
| 16 | use StreamDecoratorTrait; |
| 17 | |
| 18 | /** |
| 19 | * @var string |
| 20 | */ |
| 21 | private $buffer = ''; |
| 22 | |
| 23 | /** |
| 24 | * @var CipherMethod |
| 25 | */ |
| 26 | private $cipherMethod; |
| 27 | |
| 28 | /** |
| 29 | * @var string |
| 30 | */ |
| 31 | private $key; |
| 32 | |
| 33 | /** |
| 34 | * @var StreamInterface |
| 35 | */ |
| 36 | private $stream; |
| 37 | |
| 38 | /** |
| 39 | * @param StreamInterface $plainText |
| 40 | * @param string $key |
| 41 | * @param CipherMethod $cipherMethod |
| 42 | */ |
| 43 | public function __construct( |
| 44 | StreamInterface $plainText, |
| 45 | $key, |
| 46 | CipherMethod $cipherMethod |
| 47 | ) { |
| 48 | $this->stream = $plainText; |
| 49 | $this->key = $key; |
| 50 | $this->cipherMethod = clone $cipherMethod; |
| 51 | } |
| 52 | |
| 53 | public function getOpenSslName() |
| 54 | { |
| 55 | return $this->cipherMethod->getOpenSslName(); |
| 56 | } |
| 57 | |
| 58 | public function getAesName() |
| 59 | { |
| 60 | return $this->cipherMethod->getAesName(); |
| 61 | } |
| 62 | |
| 63 | public function getCurrentIv() |
| 64 | { |
| 65 | return $this->cipherMethod->getCurrentIv(); |
| 66 | } |
| 67 | |
| 68 | public function getSize(): ?int |
| 69 | { |
| 70 | $plainTextSize = $this->stream->getSize(); |
| 71 | |
| 72 | if ($this->cipherMethod->requiresPadding() && $plainTextSize !== null) { |
| 73 | // PKCS7 padding requires that between 1 and self::BLOCK_SIZE be |
| 74 | // added to the plaintext to make it an even number of blocks. |
| 75 | $padding = self::BLOCK_SIZE - $plainTextSize % self::BLOCK_SIZE; |
| 76 | return $plainTextSize + $padding; |
| 77 | } |
| 78 | |
| 79 | return $plainTextSize; |
| 80 | } |
| 81 | |
| 82 | public function isWritable(): bool |
| 83 | { |
| 84 | return false; |
| 85 | } |
| 86 | |
| 87 | public function read($length): string |
| 88 | { |
| 89 | if ($length > strlen($this->buffer)) { |
| 90 | $this->buffer .= $this->encryptBlock( |
| 91 | (int) |
| 92 | self::BLOCK_SIZE * ceil(($length - strlen($this->buffer)) / self::BLOCK_SIZE) |
| 93 | ); |
| 94 | } |
| 95 | |
| 96 | $data = substr($this->buffer, 0, $length); |
| 97 | $this->buffer = substr($this->buffer, $length); |
| 98 | |
| 99 | return $data ? $data : ''; |
| 100 | } |
| 101 | |
| 102 | public function seek($offset, $whence = SEEK_SET): void |
| 103 | { |
| 104 | if ($whence === SEEK_CUR) { |
| 105 | $offset = $this->tell() + $offset; |
| 106 | $whence = SEEK_SET; |
| 107 | } |
| 108 | |
| 109 | if ($whence === SEEK_SET) { |
| 110 | $this->buffer = ''; |
| 111 | $wholeBlockOffset |
| 112 | = (int) ($offset / self::BLOCK_SIZE) * self::BLOCK_SIZE; |
| 113 | $this->stream->seek($wholeBlockOffset); |
| 114 | $this->cipherMethod->seek($wholeBlockOffset); |
| 115 | $this->read($offset - $wholeBlockOffset); |
| 116 | } else { |
| 117 | throw new LogicException('Unrecognized whence.'); |
| 118 | } |
| 119 | } |
| 120 | |
| 121 | private function encryptBlock($length) |
| 122 | { |
| 123 | if ($this->stream->eof()) { |
| 124 | return ''; |
| 125 | } |
| 126 | |
| 127 | $plainText = ''; |
| 128 | do { |
| 129 | $plainText .= $this->stream->read((int) ($length - strlen($plainText))); |
| 130 | } while (strlen($plainText) < $length && !$this->stream->eof()); |
| 131 | |
| 132 | $options = OPENSSL_RAW_DATA; |
| 133 | if (!$this->stream->eof() |
| 134 | || $this->stream->getSize() !== $this->stream->tell() |
| 135 | ) { |
| 136 | $options |= OPENSSL_ZERO_PADDING; |
| 137 | } |
| 138 | |
| 139 | $cipherText = openssl_encrypt( |
| 140 | $plainText, |
| 141 | $this->cipherMethod->getOpenSslName(), |
| 142 | $this->key, |
| 143 | $options, |
| 144 | $this->cipherMethod->getCurrentIv() |
| 145 | ); |
| 146 | |
| 147 | $this->cipherMethod->update($cipherText); |
| 148 | |
| 149 | return $cipherText; |
| 150 | } |
| 151 | } |
| 152 |