summaryrefslogtreecommitdiff
path: root/vendor/aws/aws-sdk-php/src/Crypto/EncryptionTrait.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/aws/aws-sdk-php/src/Crypto/EncryptionTrait.php')
-rw-r--r--vendor/aws/aws-sdk-php/src/Crypto/EncryptionTrait.php192
1 files changed, 192 insertions, 0 deletions
diff --git a/vendor/aws/aws-sdk-php/src/Crypto/EncryptionTrait.php b/vendor/aws/aws-sdk-php/src/Crypto/EncryptionTrait.php
new file mode 100644
index 0000000..f6d1b7d
--- /dev/null
+++ b/vendor/aws/aws-sdk-php/src/Crypto/EncryptionTrait.php
@@ -0,0 +1,192 @@
+<?php
+namespace Aws\Crypto;
+
+use GuzzleHttp\Psr7;
+use GuzzleHttp\Psr7\AppendStream;
+use GuzzleHttp\Psr7\Stream;
+
+trait EncryptionTrait
+{
+ private static $allowedOptions = [
+ 'Cipher' => true,
+ 'KeySize' => true,
+ 'Aad' => true,
+ ];
+
+ /**
+ * Dependency to generate a CipherMethod from a set of inputs for loading
+ * in to an AesEncryptingStream.
+ *
+ * @param string $cipherName Name of the cipher to generate for encrypting.
+ * @param string $iv Base Initialization Vector for the cipher.
+ * @param int $keySize Size of the encryption key, in bits, that will be
+ * used.
+ *
+ * @return Cipher\CipherMethod
+ *
+ * @internal
+ */
+ abstract protected function buildCipherMethod($cipherName, $iv, $keySize);
+
+ /**
+ * Builds an AesStreamInterface and populates encryption metadata into the
+ * supplied envelope.
+ *
+ * @param Stream $plaintext Plain-text data to be encrypted using the
+ * materials, algorithm, and data provided.
+ * @param array $cipherOptions Options for use in determining the cipher to
+ * be used for encrypting data.
+ * @param MaterialsProvider $provider A provider to supply and encrypt
+ * materials used in encryption.
+ * @param MetadataEnvelope $envelope A storage envelope for encryption
+ * metadata to be added to.
+ *
+ * @return AesStreamInterface
+ *
+ * @throws \InvalidArgumentException Thrown when a value in $cipherOptions
+ * is not valid.
+ *
+ * @internal
+ */
+ public function encrypt(
+ Stream $plaintext,
+ array $cipherOptions,
+ MaterialsProvider $provider,
+ MetadataEnvelope $envelope
+ ) {
+ $materialsDescription = $provider->getMaterialsDescription();
+
+ $cipherOptions = array_intersect_key(
+ $cipherOptions,
+ self::$allowedOptions
+ );
+
+ if (empty($cipherOptions['Cipher'])) {
+ throw new \InvalidArgumentException('An encryption cipher must be'
+ . ' specified in the "cipher_options".');
+ }
+
+ if (!self::isSupportedCipher($cipherOptions['Cipher'])) {
+ throw new \InvalidArgumentException('The cipher requested is not'
+ . ' supported by the SDK.');
+ }
+
+ if (empty($cipherOptions['KeySize'])) {
+ $cipherOptions['KeySize'] = 256;
+ }
+ if (!is_int($cipherOptions['KeySize'])) {
+ throw new \InvalidArgumentException('The cipher "KeySize" must be'
+ . ' an integer.');
+ }
+
+ if (!MaterialsProvider::isSupportedKeySize(
+ $cipherOptions['KeySize']
+ )) {
+ throw new \InvalidArgumentException('The cipher "KeySize" requested'
+ . ' is not supported by AES (128, 192, or 256).');
+ }
+
+ $cipherOptions['Iv'] = $provider->generateIv(
+ $this->getCipherOpenSslName(
+ $cipherOptions['Cipher'],
+ $cipherOptions['KeySize']
+ )
+ );
+
+ $cek = $provider->generateCek($cipherOptions['KeySize']);
+
+ list($encryptingStream, $aesName) = $this->getEncryptingStream(
+ $plaintext,
+ $cek,
+ $cipherOptions
+ );
+
+ // Populate envelope data
+ $envelope[MetadataEnvelope::CONTENT_KEY_V2_HEADER] =
+ $provider->encryptCek(
+ $cek,
+ $materialsDescription
+ );
+ unset($cek);
+
+ $envelope[MetadataEnvelope::IV_HEADER] =
+ base64_encode($cipherOptions['Iv']);
+ $envelope[MetadataEnvelope::KEY_WRAP_ALGORITHM_HEADER] =
+ $provider->getWrapAlgorithmName();
+ $envelope[MetadataEnvelope::CONTENT_CRYPTO_SCHEME_HEADER] = $aesName;
+ $envelope[MetadataEnvelope::UNENCRYPTED_CONTENT_LENGTH_HEADER] =
+ strlen($plaintext);
+ $envelope[MetadataEnvelope::MATERIALS_DESCRIPTION_HEADER] =
+ json_encode($materialsDescription);
+ if (!empty($cipherOptions['Tag'])) {
+ $envelope[MetadataEnvelope::CRYPTO_TAG_LENGTH_HEADER] =
+ strlen($cipherOptions['Tag']) * 8;
+ }
+
+ return $encryptingStream;
+ }
+
+ /**
+ * Generates a stream that wraps the plaintext with the proper cipher and
+ * uses the content encryption key (CEK) to encrypt the data when read.
+ *
+ * @param Stream $plaintext Plain-text data to be encrypted using the
+ * materials, algorithm, and data provided.
+ * @param string $cek A content encryption key for use by the stream for
+ * encrypting the plaintext data.
+ * @param array $cipherOptions Options for use in determining the cipher to
+ * be used for encrypting data.
+ *
+ * @return [AesStreamInterface, string]
+ *
+ * @internal
+ */
+ protected function getEncryptingStream(
+ Stream $plaintext,
+ $cek,
+ &$cipherOptions
+ ) {
+ switch ($cipherOptions['Cipher']) {
+ case 'gcm':
+ $cipherOptions['TagLength'] = 16;
+
+ $cipherTextStream = new AesGcmEncryptingStream(
+ $plaintext,
+ $cek,
+ $cipherOptions['Iv'],
+ $cipherOptions['Aad'] = isset($cipherOptions['Aad'])
+ ? $cipherOptions['Aad']
+ : null,
+ $cipherOptions['TagLength'],
+ $cipherOptions['KeySize']
+ );
+
+ if (!empty($cipherOptions['Aad'])) {
+ trigger_error("'Aad' has been supplied for content encryption"
+ . " with " . $cipherTextStream->getAesName() . ". The"
+ . " PHP SDK encryption client can decrypt an object"
+ . " encrypted in this way, but other AWS SDKs may not be"
+ . " able to.", E_USER_WARNING);
+ }
+
+ $appendStream = new AppendStream([
+ $cipherTextStream->createStream()
+ ]);
+ $cipherOptions['Tag'] = $cipherTextStream->getTag();
+ $appendStream->addStream(Psr7\Utils::streamFor($cipherOptions['Tag']));
+ return [$appendStream, $cipherTextStream->getAesName()];
+ default:
+ $cipherMethod = $this->buildCipherMethod(
+ $cipherOptions['Cipher'],
+ $cipherOptions['Iv'],
+ $cipherOptions['KeySize']
+ );
+ $cipherTextStream = new AesEncryptingStream(
+ $plaintext,
+ $cek,
+ $cipherMethod
+ );
+ return [$cipherTextStream, $cipherTextStream->getAesName()];
+ }
+ }
+}