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 / EncryptionTrait.php

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

115 lines 6.0 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 trait EncryptionTrait
9 {
10 private static $allowedOptions = ['Cipher' => \true, 'KeySize' => \true, 'Aad' => \true];
11 /**
12 * Dependency to generate a CipherMethod from a set of inputs for loading
13 * in to an AesEncryptingStream.
14 *
15 * @param string $cipherName Name of the cipher to generate for encrypting.
16 * @param string $iv Base Initialization Vector for the cipher.
17 * @param int $keySize Size of the encryption key, in bits, that will be
18 * used.
19 *
20 * @return Cipher\CipherMethod
21 *
22 * @internal
23 */
24 protected abstract function buildCipherMethod($cipherName, $iv, $keySize);
25 /**
26 * Builds an AesStreamInterface and populates encryption metadata into the
27 * supplied envelope.
28 *
29 * @param Stream $plaintext Plain-text data to be encrypted using the
30 * materials, algorithm, and data provided.
31 * @param array $cipherOptions Options for use in determining the cipher to
32 * be used for encrypting data.
33 * @param MaterialsProvider $provider A provider to supply and encrypt
34 * materials used in encryption.
35 * @param MetadataEnvelope $envelope A storage envelope for encryption
36 * metadata to be added to.
37 *
38 * @return AesStreamInterface
39 *
40 * @throws \InvalidArgumentException Thrown when a value in $cipherOptions
41 * is not valid.
42 *
43 * @internal
44 */
45 public function encrypt(Stream $plaintext, array $cipherOptions, MaterialsProvider $provider, MetadataEnvelope $envelope)
46 {
47 $materialsDescription = $provider->getMaterialsDescription();
48 $cipherOptions = \array_intersect_key($cipherOptions, self::$allowedOptions);
49 if (empty($cipherOptions['Cipher'])) {
50 throw new \InvalidArgumentException('An encryption cipher must be' . ' specified in the "cipher_options".');
51 }
52 if (!self::isSupportedCipher($cipherOptions['Cipher'])) {
53 throw new \InvalidArgumentException('The cipher requested is not' . ' supported by the SDK.');
54 }
55 if (empty($cipherOptions['KeySize'])) {
56 $cipherOptions['KeySize'] = 256;
57 }
58 if (!\is_int($cipherOptions['KeySize'])) {
59 throw new \InvalidArgumentException('The cipher "KeySize" must be' . ' an integer.');
60 }
61 if (!MaterialsProvider::isSupportedKeySize($cipherOptions['KeySize'])) {
62 throw new \InvalidArgumentException('The cipher "KeySize" requested' . ' is not supported by AES (128, 192, or 256).');
63 }
64 $cipherOptions['Iv'] = $provider->generateIv($this->getCipherOpenSslName($cipherOptions['Cipher'], $cipherOptions['KeySize']));
65 $cek = $provider->generateCek($cipherOptions['KeySize']);
66 list($encryptingStream, $aesName) = $this->getEncryptingStream($plaintext, $cek, $cipherOptions);
67 // Populate envelope data
68 $envelope[MetadataEnvelope::CONTENT_KEY_V2_HEADER] = $provider->encryptCek($cek, $materialsDescription);
69 unset($cek);
70 $envelope[MetadataEnvelope::IV_HEADER] = \base64_encode($cipherOptions['Iv']);
71 $envelope[MetadataEnvelope::KEY_WRAP_ALGORITHM_HEADER] = $provider->getWrapAlgorithmName();
72 $envelope[MetadataEnvelope::CONTENT_CRYPTO_SCHEME_HEADER] = $aesName;
73 $envelope[MetadataEnvelope::UNENCRYPTED_CONTENT_LENGTH_HEADER] = \strlen($plaintext);
74 $envelope[MetadataEnvelope::MATERIALS_DESCRIPTION_HEADER] = \json_encode($materialsDescription);
75 if (!empty($cipherOptions['Tag'])) {
76 $envelope[MetadataEnvelope::CRYPTO_TAG_LENGTH_HEADER] = \strlen($cipherOptions['Tag']) * 8;
77 }
78 return $encryptingStream;
79 }
80 /**
81 * Generates a stream that wraps the plaintext with the proper cipher and
82 * uses the content encryption key (CEK) to encrypt the data when read.
83 *
84 * @param Stream $plaintext Plain-text data to be encrypted using the
85 * materials, algorithm, and data provided.
86 * @param string $cek A content encryption key for use by the stream for
87 * encrypting the plaintext data.
88 * @param array $cipherOptions Options for use in determining the cipher to
89 * be used for encrypting data.
90 *
91 * @return [AesStreamInterface, string]
92 *
93 * @internal
94 */
95 protected function getEncryptingStream(Stream $plaintext, $cek, &$cipherOptions)
96 {
97 switch ($cipherOptions['Cipher']) {
98 case 'gcm':
99 $cipherOptions['TagLength'] = 16;
100 $cipherTextStream = new AesGcmEncryptingStream($plaintext, $cek, $cipherOptions['Iv'], $cipherOptions['Aad'] = isset($cipherOptions['Aad']) ? $cipherOptions['Aad'] : null, $cipherOptions['TagLength'], $cipherOptions['KeySize']);
101 if (!empty($cipherOptions['Aad'])) {
102 \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);
103 }
104 $appendStream = new AppendStream([$cipherTextStream->createStream()]);
105 $cipherOptions['Tag'] = $cipherTextStream->getTag();
106 $appendStream->addStream(Psr7\Utils::streamFor($cipherOptions['Tag']));
107 return [$appendStream, $cipherTextStream->getAesName()];
108 default:
109 $cipherMethod = $this->buildCipherMethod($cipherOptions['Cipher'], $cipherOptions['Iv'], $cipherOptions['KeySize']);
110 $cipherTextStream = new AesEncryptingStream($plaintext, $cek, $cipherMethod);
111 return [$cipherTextStream, $cipherTextStream->getAesName()];
112 }
113 }
114 }
115