PluginProbe
Media Cloud Sync / 1.0.0
Media Cloud Sync v1.0.0
1.4.1 1.4.0 1.3.12 1.3.11 1.3.10 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.2.0 1.2.10 1.2.11 1.2.12 1.2.13 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 All 35 releases
media-cloud-sync / includes / sdk / s3 / Aws / Crypto / EncryptionTraitV2.php

EncryptionTraitV2.php in Media Cloud Sync 1.0.0, at includes/sdk/s3/Aws/Crypto/EncryptionTraitV2.php

123 lines 6.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Dudlewebs\WPMCS\s3\Aws\Crypto;
4
5 use Dudlewebs\WPMCS\s3\GuzzleHttp\Psr7;
6 use Dudlewebs\WPMCS\s3\GuzzleHttp\Psr7\AppendStream;
7 use Dudlewebs\WPMCS\s3\GuzzleHttp\Psr7\Stream;
8 use Dudlewebs\WPMCS\s3\Psr\Http\Message\StreamInterface;
9 trait EncryptionTraitV2
10 {
11 private static $allowedOptions = ['Cipher' => \true, 'KeySize' => \true, 'Aad' => \true];
12 private static $encryptClasses = ['gcm' => AesGcmEncryptingStream::class];
13 /**
14 * Dependency to generate a CipherMethod from a set of inputs for loading
15 * in to an AesEncryptingStream.
16 *
17 * @param string $cipherName Name of the cipher to generate for encrypting.
18 * @param string $iv Base Initialization Vector for the cipher.
19 * @param int $keySize Size of the encryption key, in bits, that will be
20 * used.
21 *
22 * @return Cipher\CipherMethod
23 *
24 * @internal
25 */
26 protected abstract function buildCipherMethod($cipherName, $iv, $keySize);
27 /**
28 * Builds an AesStreamInterface and populates encryption metadata into the
29 * supplied envelope.
30 *
31 * @param Stream $plaintext Plain-text data to be encrypted using the
32 * materials, algorithm, and data provided.
33 * @param array $options Options for use in encryption, including cipher
34 * options, and encryption context.
35 * @param MaterialsProviderV2 $provider A provider to supply and encrypt
36 * materials used in encryption.
37 * @param MetadataEnvelope $envelope A storage envelope for encryption
38 * metadata to be added to.
39 *
40 * @return StreamInterface
41 *
42 * @throws \InvalidArgumentException Thrown when a value in $options['@CipherOptions']
43 * is not valid.
44 *s
45 * @internal
46 */
47 public function encrypt(Stream $plaintext, array $options, MaterialsProviderV2 $provider, MetadataEnvelope $envelope)
48 {
49 $options = \array_change_key_case($options);
50 $cipherOptions = \array_intersect_key($options['@cipheroptions'], self::$allowedOptions);
51 if (empty($cipherOptions['Cipher'])) {
52 throw new \InvalidArgumentException('An encryption cipher must be' . ' specified in @CipherOptions["Cipher"].');
53 }
54 $cipherOptions['Cipher'] = \strtolower($cipherOptions['Cipher']);
55 if (!self::isSupportedCipher($cipherOptions['Cipher'])) {
56 throw new \InvalidArgumentException('The cipher requested is not' . ' supported by the SDK.');
57 }
58 if (empty($cipherOptions['KeySize'])) {
59 $cipherOptions['KeySize'] = 256;
60 }
61 if (!\is_int($cipherOptions['KeySize'])) {
62 throw new \InvalidArgumentException('The cipher "KeySize" must be' . ' an integer.');
63 }
64 if (!MaterialsProviderV2::isSupportedKeySize($cipherOptions['KeySize'])) {
65 throw new \InvalidArgumentException('The cipher "KeySize" requested' . ' is not supported by AES (128 or 256).');
66 }
67 $cipherOptions['Iv'] = $provider->generateIv($this->getCipherOpenSslName($cipherOptions['Cipher'], $cipherOptions['KeySize']));
68 $encryptClass = self::$encryptClasses[$cipherOptions['Cipher']];
69 $aesName = $encryptClass::getStaticAesName();
70 $materialsDescription = ['aws:x-amz-cek-alg' => $aesName];
71 $keys = $provider->generateCek($cipherOptions['KeySize'], $materialsDescription, $options);
72 // Some providers modify materials description based on options
73 if (isset($keys['UpdatedContext'])) {
74 $materialsDescription = $keys['UpdatedContext'];
75 }
76 $encryptingStream = $this->getEncryptingStream($plaintext, $keys['Plaintext'], $cipherOptions);
77 // Populate envelope data
78 $envelope[MetadataEnvelope::CONTENT_KEY_V2_HEADER] = $keys['Ciphertext'];
79 unset($keys);
80 $envelope[MetadataEnvelope::IV_HEADER] = \base64_encode($cipherOptions['Iv']);
81 $envelope[MetadataEnvelope::KEY_WRAP_ALGORITHM_HEADER] = $provider->getWrapAlgorithmName();
82 $envelope[MetadataEnvelope::CONTENT_CRYPTO_SCHEME_HEADER] = $aesName;
83 $envelope[MetadataEnvelope::UNENCRYPTED_CONTENT_LENGTH_HEADER] = \strlen($plaintext);
84 $envelope[MetadataEnvelope::MATERIALS_DESCRIPTION_HEADER] = \json_encode($materialsDescription);
85 if (!empty($cipherOptions['Tag'])) {
86 $envelope[MetadataEnvelope::CRYPTO_TAG_LENGTH_HEADER] = \strlen($cipherOptions['Tag']) * 8;
87 }
88 return $encryptingStream;
89 }
90 /**
91 * Generates a stream that wraps the plaintext with the proper cipher and
92 * uses the content encryption key (CEK) to encrypt the data when read.
93 *
94 * @param Stream $plaintext Plain-text data to be encrypted using the
95 * materials, algorithm, and data provided.
96 * @param string $cek A content encryption key for use by the stream for
97 * encrypting the plaintext data.
98 * @param array $cipherOptions Options for use in determining the cipher to
99 * be used for encrypting data.
100 *
101 * @return [AesStreamInterface, string]
102 *
103 * @internal
104 */
105 protected function getEncryptingStream(Stream $plaintext, $cek, &$cipherOptions)
106 {
107 switch ($cipherOptions['Cipher']) {
108 // Only 'gcm' is supported for encryption currently
109 case 'gcm':
110 $cipherOptions['TagLength'] = 16;
111 $encryptClass = self::$encryptClasses['gcm'];
112 $cipherTextStream = new $encryptClass($plaintext, $cek, $cipherOptions['Iv'], $cipherOptions['Aad'] = isset($cipherOptions['Aad']) ? $cipherOptions['Aad'] : '', $cipherOptions['TagLength'], $cipherOptions['KeySize']);
113 if (!empty($cipherOptions['Aad'])) {
114 \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);
115 }
116 $appendStream = new AppendStream([$cipherTextStream->createStream()]);
117 $cipherOptions['Tag'] = $cipherTextStream->getTag();
118 $appendStream->addStream(Psr7\Utils::streamFor($cipherOptions['Tag']));
119 return $appendStream;
120 }
121 }
122 }
123