| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 | 
							- <?php
 
- namespace Aws\Crypto;
 
- use GuzzleHttp\Psr7;
 
- use GuzzleHttp\Psr7\AppendStream;
 
- use GuzzleHttp\Psr7\Stream;
 
- use Psr\Http\Message\StreamInterface;
 
- trait EncryptionTraitV2
 
- {
 
-     private static $allowedOptions = [
 
-         'Cipher' => true,
 
-         'KeySize' => true,
 
-         'Aad' => true,
 
-     ];
 
-     private static $encryptClasses = [
 
-         'gcm' => AesGcmEncryptingStream::class
 
-     ];
 
-     /**
 
-      * 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 $options    Options for use in encryption, including cipher
 
-      *                          options, and encryption context.
 
-      * @param MaterialsProviderV2 $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 StreamInterface
 
-      *
 
-      * @throws \InvalidArgumentException Thrown when a value in $options['@CipherOptions']
 
-      *                                   is not valid.
 
-      *s
 
-      * @internal
 
-      */
 
-     public function encrypt(
 
-         Stream $plaintext,
 
-         array $options,
 
-         MaterialsProviderV2 $provider,
 
-         MetadataEnvelope $envelope
 
-     ) {
 
-         $options = array_change_key_case($options);
 
-         $cipherOptions = array_intersect_key(
 
-             $options['@cipheroptions'],
 
-             self::$allowedOptions
 
-         );
 
-         if (empty($cipherOptions['Cipher'])) {
 
-             throw new \InvalidArgumentException('An encryption cipher must be'
 
-                 . ' specified in @CipherOptions["Cipher"].');
 
-         }
 
-         $cipherOptions['Cipher'] = strtolower($cipherOptions['Cipher']);
 
-         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 (!MaterialsProviderV2::isSupportedKeySize(
 
-             $cipherOptions['KeySize']
 
-         )) {
 
-             throw new \InvalidArgumentException('The cipher "KeySize" requested'
 
-                 . ' is not supported by AES (128 or 256).');
 
-         }
 
-         $cipherOptions['Iv'] = $provider->generateIv(
 
-             $this->getCipherOpenSslName(
 
-                 $cipherOptions['Cipher'],
 
-                 $cipherOptions['KeySize']
 
-             )
 
-         );
 
-         $encryptClass = self::$encryptClasses[$cipherOptions['Cipher']];
 
-         $aesName = $encryptClass::getStaticAesName();
 
-         $materialsDescription = ['aws:x-amz-cek-alg' => $aesName];
 
-         $keys = $provider->generateCek(
 
-             $cipherOptions['KeySize'],
 
-             $materialsDescription,
 
-             $options
 
-         );
 
-         // Some providers modify materials description based on options
 
-         if (isset($keys['UpdatedContext'])) {
 
-             $materialsDescription = $keys['UpdatedContext'];
 
-         }
 
-         $encryptingStream = $this->getEncryptingStream(
 
-             $plaintext,
 
-             $keys['Plaintext'],
 
-             $cipherOptions
 
-         );
 
-         // Populate envelope data
 
-         $envelope[MetadataEnvelope::CONTENT_KEY_V2_HEADER] = $keys['Ciphertext'];
 
-         unset($keys);
 
-         $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 array returns an array with two elements as follows: [string, AesStreamInterface]
 
-      *
 
-      * @internal
 
-      */
 
-     protected function getEncryptingStream(
 
-         Stream $plaintext,
 
-         $cek,
 
-         &$cipherOptions
 
-     ) {
 
-         switch ($cipherOptions['Cipher']) {
 
-             // Only 'gcm' is supported for encryption currently
 
-             case 'gcm':
 
-                 $cipherOptions['TagLength'] = 16;
 
-                 $encryptClass = self::$encryptClasses['gcm'];
 
-                 $cipherTextStream = new $encryptClass(
 
-                     $plaintext,
 
-                     $cek,
 
-                     $cipherOptions['Iv'],
 
-                     $cipherOptions['Aad'] = isset($cipherOptions['Aad'])
 
-                         ? $cipherOptions['Aad']
 
-                         : '',
 
-                     $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;
 
-         }
 
-     }
 
- }
 
 
  |