PluginProbe ʕ •ᴥ•ʔ
Transferito: WP Migration / trunk
Transferito: WP Migration vtrunk
trunk 11.4.0 12.0.0 13.1.0 14.0.0 14.0.11 14.0.7 14.1.0 14.1.1 14.1.2 14.1.3 14.1.4
transferito / vendor / aws / aws-sdk-php / src / Crypto / EncryptionTraitV2.php
transferito / vendor / aws / aws-sdk-php / src / Crypto Last commit date
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
EncryptionTraitV2.php
197 lines
1 <?php
2 namespace Aws\Crypto;
3
4 use GuzzleHttp\Psr7;
5 use GuzzleHttp\Psr7\AppendStream;
6 use GuzzleHttp\Psr7\Stream;
7 use Psr\Http\Message\StreamInterface;
8
9 trait EncryptionTraitV2
10 {
11 private static $allowedOptions = [
12 'Cipher' => true,
13 'KeySize' => true,
14 'Aad' => true,
15 ];
16
17 private static $encryptClasses = [
18 'gcm' => AesGcmEncryptingStream::class
19 ];
20
21 /**
22 * Dependency to generate a CipherMethod from a set of inputs for loading
23 * in to an AesEncryptingStream.
24 *
25 * @param string $cipherName Name of the cipher to generate for encrypting.
26 * @param string $iv Base Initialization Vector for the cipher.
27 * @param int $keySize Size of the encryption key, in bits, that will be
28 * used.
29 *
30 * @return Cipher\CipherMethod
31 *
32 * @internal
33 */
34 abstract protected function buildCipherMethod($cipherName, $iv, $keySize);
35
36 /**
37 * Builds an AesStreamInterface and populates encryption metadata into the
38 * supplied envelope.
39 *
40 * @param Stream $plaintext Plain-text data to be encrypted using the
41 * materials, algorithm, and data provided.
42 * @param array $options Options for use in encryption, including cipher
43 * options, and encryption context.
44 * @param MaterialsProviderV2 $provider A provider to supply and encrypt
45 * materials used in encryption.
46 * @param MetadataEnvelope $envelope A storage envelope for encryption
47 * metadata to be added to.
48 *
49 * @return StreamInterface
50 *
51 * @throws \InvalidArgumentException Thrown when a value in $options['@CipherOptions']
52 * is not valid.
53 *s
54 * @internal
55 */
56 public function encrypt(
57 Stream $plaintext,
58 array $options,
59 MaterialsProviderV2 $provider,
60 MetadataEnvelope $envelope
61 ) {
62 $options = array_change_key_case($options);
63 $cipherOptions = array_intersect_key(
64 $options['@cipheroptions'],
65 self::$allowedOptions
66 );
67
68 if (empty($cipherOptions['Cipher'])) {
69 throw new \InvalidArgumentException('An encryption cipher must be'
70 . ' specified in @CipherOptions["Cipher"].');
71 }
72
73 $cipherOptions['Cipher'] = strtolower($cipherOptions['Cipher']);
74
75 if (!self::isSupportedCipher($cipherOptions['Cipher'])) {
76 throw new \InvalidArgumentException('The cipher requested is not'
77 . ' supported by the SDK.');
78 }
79
80 if (empty($cipherOptions['KeySize'])) {
81 $cipherOptions['KeySize'] = 256;
82 }
83 if (!is_int($cipherOptions['KeySize'])) {
84 throw new \InvalidArgumentException('The cipher "KeySize" must be'
85 . ' an integer.');
86 }
87
88 if (!MaterialsProviderV2::isSupportedKeySize(
89 $cipherOptions['KeySize']
90 )) {
91 throw new \InvalidArgumentException('The cipher "KeySize" requested'
92 . ' is not supported by AES (128 or 256).');
93 }
94
95 $cipherOptions['Iv'] = $provider->generateIv(
96 $this->getCipherOpenSslName(
97 $cipherOptions['Cipher'],
98 $cipherOptions['KeySize']
99 )
100 );
101
102 $encryptClass = self::$encryptClasses[$cipherOptions['Cipher']];
103 $aesName = $encryptClass::getStaticAesName();
104 $materialsDescription = ['aws:x-amz-cek-alg' => $aesName];
105
106 $keys = $provider->generateCek(
107 $cipherOptions['KeySize'],
108 $materialsDescription,
109 $options
110 );
111
112 // Some providers modify materials description based on options
113 if (isset($keys['UpdatedContext'])) {
114 $materialsDescription = $keys['UpdatedContext'];
115 }
116
117 $encryptingStream = $this->getEncryptingStream(
118 $plaintext,
119 $keys['Plaintext'],
120 $cipherOptions
121 );
122
123 // Populate envelope data
124 $envelope[MetadataEnvelope::CONTENT_KEY_V2_HEADER] = $keys['Ciphertext'];
125 unset($keys);
126
127 $envelope[MetadataEnvelope::IV_HEADER] =
128 base64_encode($cipherOptions['Iv']);
129 $envelope[MetadataEnvelope::KEY_WRAP_ALGORITHM_HEADER] =
130 $provider->getWrapAlgorithmName();
131 $envelope[MetadataEnvelope::CONTENT_CRYPTO_SCHEME_HEADER] = $aesName;
132 $envelope[MetadataEnvelope::UNENCRYPTED_CONTENT_LENGTH_HEADER] =
133 strlen($plaintext);
134 $envelope[MetadataEnvelope::MATERIALS_DESCRIPTION_HEADER] =
135 json_encode($materialsDescription);
136 if (!empty($cipherOptions['Tag'])) {
137 $envelope[MetadataEnvelope::CRYPTO_TAG_LENGTH_HEADER] =
138 strlen($cipherOptions['Tag']) * 8;
139 }
140
141 return $encryptingStream;
142 }
143
144 /**
145 * Generates a stream that wraps the plaintext with the proper cipher and
146 * uses the content encryption key (CEK) to encrypt the data when read.
147 *
148 * @param Stream $plaintext Plain-text data to be encrypted using the
149 * materials, algorithm, and data provided.
150 * @param string $cek A content encryption key for use by the stream for
151 * encrypting the plaintext data.
152 * @param array $cipherOptions Options for use in determining the cipher to
153 * be used for encrypting data.
154 *
155 * @return [AesStreamInterface, string]
156 *
157 * @internal
158 */
159 protected function getEncryptingStream(
160 Stream $plaintext,
161 $cek,
162 &$cipherOptions
163 ) {
164 switch ($cipherOptions['Cipher']) {
165 // Only 'gcm' is supported for encryption currently
166 case 'gcm':
167 $cipherOptions['TagLength'] = 16;
168 $encryptClass = self::$encryptClasses['gcm'];
169 $cipherTextStream = new $encryptClass(
170 $plaintext,
171 $cek,
172 $cipherOptions['Iv'],
173 $cipherOptions['Aad'] = isset($cipherOptions['Aad'])
174 ? $cipherOptions['Aad']
175 : '',
176 $cipherOptions['TagLength'],
177 $cipherOptions['KeySize']
178 );
179
180 if (!empty($cipherOptions['Aad'])) {
181 trigger_error("'Aad' has been supplied for content encryption"
182 . " with " . $cipherTextStream->getAesName() . ". The"
183 . " PHP SDK encryption client can decrypt an object"
184 . " encrypted in this way, but other AWS SDKs may not be"
185 . " able to.", E_USER_WARNING);
186 }
187
188 $appendStream = new AppendStream([
189 $cipherTextStream->createStream()
190 ]);
191 $cipherOptions['Tag'] = $cipherTextStream->getTag();
192 $appendStream->addStream(Psr7\Utils::streamFor($cipherOptions['Tag']));
193 return $appendStream;
194 }
195 }
196 }
197