allow vendord
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m3s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 16s
Build, Push and Deploy / deploy-staging (push) Successful in 32s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m3s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 16s
Build, Push and Deploy / deploy-staging (push) Successful in 32s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s
This commit is contained in:
121
vendor/aws/aws-sdk-php/src/Crypto/AbstractCryptoClient.php
vendored
Normal file
121
vendor/aws/aws-sdk-php/src/Crypto/AbstractCryptoClient.php
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
namespace Aws\Crypto;
|
||||
|
||||
use Aws\Crypto\Cipher\CipherMethod;
|
||||
use Aws\Crypto\Cipher\Cbc;
|
||||
use GuzzleHttp\Psr7\Stream;
|
||||
|
||||
/**
|
||||
* Legacy abstract encryption client. New workflows should use
|
||||
* AbstractCryptoClientV2.
|
||||
*
|
||||
* @deprecated
|
||||
* @internal
|
||||
*/
|
||||
abstract class AbstractCryptoClient
|
||||
{
|
||||
public static $supportedCiphers = ['cbc', 'gcm'];
|
||||
|
||||
public static $supportedKeyWraps = [
|
||||
KmsMaterialsProvider::WRAP_ALGORITHM_NAME
|
||||
];
|
||||
|
||||
/**
|
||||
* Returns if the passed cipher name is supported for encryption by the SDK.
|
||||
*
|
||||
* @param string $cipherName The name of a cipher to verify is registered.
|
||||
*
|
||||
* @return bool If the cipher passed is in our supported list.
|
||||
*/
|
||||
public static function isSupportedCipher($cipherName)
|
||||
{
|
||||
return in_array($cipherName, self::$supportedCiphers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an identifier recognizable by `openssl_*` functions, such as
|
||||
* `aes-256-cbc` or `aes-128-ctr`.
|
||||
*
|
||||
* @param string $cipherName Name of the cipher being used for encrypting
|
||||
* or decrypting.
|
||||
* @param int $keySize Size of the encryption key, in bits, that will be
|
||||
* used.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function getCipherOpenSslName($cipherName, $keySize);
|
||||
|
||||
/**
|
||||
* Constructs a CipherMethod for the given name, initialized with the other
|
||||
* data passed for use in encrypting or decrypting.
|
||||
*
|
||||
* @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 CipherMethod
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
abstract protected function buildCipherMethod($cipherName, $iv, $keySize);
|
||||
|
||||
/**
|
||||
* Performs a reverse lookup to get the openssl_* cipher name from the
|
||||
* AESName passed in from the MetadataEnvelope.
|
||||
*
|
||||
* @param $aesName
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
abstract protected function getCipherFromAesName($aesName);
|
||||
|
||||
/**
|
||||
* Dependency to provide an interface for building an encryption stream for
|
||||
* data given cipher details, metadata, and materials to do so.
|
||||
*
|
||||
* @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
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
abstract public function encrypt(
|
||||
Stream $plaintext,
|
||||
array $cipherOptions,
|
||||
MaterialsProvider $provider,
|
||||
MetadataEnvelope $envelope
|
||||
);
|
||||
|
||||
/**
|
||||
* Dependency to provide an interface for building a decryption stream for
|
||||
* cipher text given metadata and materials to do so.
|
||||
*
|
||||
* @param string $cipherText Plain-text data to be decrypted using the
|
||||
* materials, algorithm, and data provided.
|
||||
* @param MaterialsProviderInterface $provider A provider to supply and encrypt
|
||||
* materials used in encryption.
|
||||
* @param MetadataEnvelope $envelope A storage envelope for encryption
|
||||
* metadata to be read from.
|
||||
* @param array $cipherOptions Additional verification options.
|
||||
*
|
||||
* @return AesStreamInterface
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
abstract public function decrypt(
|
||||
$cipherText,
|
||||
MaterialsProviderInterface $provider,
|
||||
MetadataEnvelope $envelope,
|
||||
array $cipherOptions = []
|
||||
);
|
||||
}
|
||||
135
vendor/aws/aws-sdk-php/src/Crypto/AbstractCryptoClientV2.php
vendored
Normal file
135
vendor/aws/aws-sdk-php/src/Crypto/AbstractCryptoClientV2.php
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
namespace Aws\Crypto;
|
||||
|
||||
use Aws\Crypto\Cipher\CipherMethod;
|
||||
use GuzzleHttp\Psr7\Stream;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
abstract class AbstractCryptoClientV2
|
||||
{
|
||||
const KEY_COMMITMENT_POLICIES = [
|
||||
'FORBID_ENCRYPT_ALLOW_DECRYPT'
|
||||
];
|
||||
|
||||
public static $supportedCiphers = ['gcm'];
|
||||
|
||||
public static $supportedKeyWraps = [
|
||||
KmsMaterialsProviderV2::WRAP_ALGORITHM_NAME
|
||||
];
|
||||
|
||||
public static $supportedSecurityProfiles = ['V2', 'V2_AND_LEGACY'];
|
||||
|
||||
public static $legacySecurityProfiles = ['V2_AND_LEGACY'];
|
||||
|
||||
/**
|
||||
* Returns if the passed policy name is supported for encryption by the SDK.
|
||||
*
|
||||
* @param string $policy The name of a key commitment policy to verify is registered.
|
||||
*
|
||||
* @return bool If the key commitment policy passed is in our supported list.
|
||||
*/
|
||||
public static function isSupportedKeyCommitmentPolicy(string $policy): bool
|
||||
{
|
||||
return in_array($policy, self::KEY_COMMITMENT_POLICIES, strict: true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the passed cipher name is supported for encryption by the SDK.
|
||||
*
|
||||
* @param string $cipherName The name of a cipher to verify is registered.
|
||||
*
|
||||
* @return bool If the cipher passed is in our supported list.
|
||||
*/
|
||||
public static function isSupportedCipher($cipherName)
|
||||
{
|
||||
return in_array($cipherName, self::$supportedCiphers, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an identifier recognizable by `openssl_*` functions, such as
|
||||
* `aes-256-gcm`
|
||||
*
|
||||
* @param string $cipherName Name of the cipher being used for encrypting
|
||||
* or decrypting.
|
||||
* @param int $keySize Size of the encryption key, in bits, that will be
|
||||
* used.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function getCipherOpenSslName($cipherName, $keySize);
|
||||
|
||||
/**
|
||||
* Constructs a CipherMethod for the given name, initialized with the other
|
||||
* data passed for use in encrypting or decrypting.
|
||||
*
|
||||
* @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 CipherMethod
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
abstract protected function buildCipherMethod($cipherName, $iv, $keySize);
|
||||
|
||||
/**
|
||||
* Performs a reverse lookup to get the openssl_* cipher name from the
|
||||
* AESName passed in from the MetadataEnvelope.
|
||||
*
|
||||
* @param $aesName
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
abstract protected function getCipherFromAesName($aesName);
|
||||
|
||||
/**
|
||||
* Dependency to provide an interface for building an encryption stream for
|
||||
* data given cipher details, metadata, and materials to do so.
|
||||
*
|
||||
* @param Stream $plaintext Plain-text data to be encrypted using the
|
||||
* materials, algorithm, and data provided.
|
||||
* @param array $options Options for use in encryption.
|
||||
* @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 AesStreamInterface
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
abstract public function encrypt(
|
||||
Stream $plaintext,
|
||||
array $options,
|
||||
MaterialsProviderV2 $provider,
|
||||
MetadataEnvelope $envelope
|
||||
);
|
||||
|
||||
/**
|
||||
* Dependency to provide an interface for building a decryption stream for
|
||||
* cipher text given metadata and materials to do so.
|
||||
*
|
||||
* @param string $cipherText Plain-text data to be decrypted using the
|
||||
* materials, algorithm, and data provided.
|
||||
* @param MaterialsProviderInterface $provider A provider to supply and encrypt
|
||||
* materials used in encryption.
|
||||
* @param MetadataEnvelope $envelope A storage envelope for encryption
|
||||
* metadata to be read from.
|
||||
* @param array $options Options used for decryption.
|
||||
*
|
||||
* @return AesStreamInterface
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
abstract public function decrypt(
|
||||
$cipherText,
|
||||
MaterialsProviderInterfaceV2 $provider,
|
||||
MetadataEnvelope $envelope,
|
||||
array $options = []
|
||||
);
|
||||
}
|
||||
151
vendor/aws/aws-sdk-php/src/Crypto/AbstractCryptoClientV3.php
vendored
Normal file
151
vendor/aws/aws-sdk-php/src/Crypto/AbstractCryptoClientV3.php
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
namespace Aws\Crypto;
|
||||
|
||||
use Aws\Crypto\Cipher\CipherMethod;
|
||||
use GuzzleHttp\Psr7\AppendStream;
|
||||
use GuzzleHttp\Psr7\Stream;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
abstract class AbstractCryptoClientV3
|
||||
{
|
||||
const SUPPORTED_SECURITY_PROFILES = ['V3', 'V3_AND_LEGACY'];
|
||||
|
||||
const LEGACY_SECURITY_PROFILES = ['V3_AND_LEGACY'];
|
||||
|
||||
const KEY_COMMITMENT_POLICIES = [
|
||||
'FORBID_ENCRYPT_ALLOW_DECRYPT',
|
||||
'REQUIRE_ENCRYPT_ALLOW_DECRYPT',
|
||||
'REQUIRE_ENCRYPT_REQUIRE_DECRYPT'
|
||||
];
|
||||
|
||||
public static array $supportedCiphers = ['gcm'];
|
||||
|
||||
public static array $supportedKeyWraps = [
|
||||
KmsMaterialsProviderV3::WRAP_ALGORITHM_NAME
|
||||
];
|
||||
|
||||
/**
|
||||
* Returns if the passed policy name is supported for encryption by the SDK.
|
||||
*
|
||||
* @param string $policy The name of a key commitment policy to verify is registered.
|
||||
*
|
||||
* @return bool If the key commitment policy passed is in our supported list.
|
||||
*/
|
||||
public static function isSupportedKeyCommitmentPolicy(string $policy): bool
|
||||
{
|
||||
return in_array($policy, AbstractCryptoClientV3::KEY_COMMITMENT_POLICIES, strict: true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the passed cipher name is supported for encryption by the SDK.
|
||||
*
|
||||
* @param string $cipherName The name of a cipher to verify is registered.
|
||||
*
|
||||
* @return bool If the cipher passed is in our supported list.
|
||||
*/
|
||||
public static function isSupportedCipher(string $cipherName): bool
|
||||
{
|
||||
return in_array($cipherName, self::$supportedCiphers, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an identifier recognizable by `openssl_*` functions, such as
|
||||
* `aes-256-gcm`
|
||||
*
|
||||
* @param string $cipherName Name of the cipher being used for encrypting
|
||||
* or decrypting.
|
||||
* @param int $keySize Size of the encryption key, in bits, that will be
|
||||
* used.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function getCipherOpenSslName(
|
||||
$cipherName,
|
||||
$keySize
|
||||
);
|
||||
|
||||
/**
|
||||
* Constructs a CipherMethod for the given name, initialized with the other
|
||||
* data passed for use in encrypting or decrypting.
|
||||
*
|
||||
* @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 CipherMethod
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
abstract protected function buildCipherMethod(
|
||||
$cipherName,
|
||||
$iv,
|
||||
$keySize
|
||||
);
|
||||
|
||||
/**
|
||||
* Performs a reverse lookup to get the openssl_* cipher name from the
|
||||
* AESName passed in from the MetadataEnvelope.
|
||||
*
|
||||
* @param string $aesName
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
abstract protected function getCipherFromAesName($aesName);
|
||||
|
||||
/**
|
||||
* Dependency to provide an interface for building an encryption stream for
|
||||
* data given cipher details, metadata, and materials to do so.
|
||||
*
|
||||
* @param Stream $plaintext Plain-text data to be encrypted using the
|
||||
* materials, algorithm, and data provided.
|
||||
* @param AlgorithmSuite $algorithmSuite AlgorithmSuite for use in encryption.
|
||||
* @param array $options Options for use in encryption, including cipher
|
||||
* options, and encryption context.
|
||||
* @param MaterialsProviderV3 $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 AppendStream
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
abstract public function encrypt(
|
||||
Stream $plaintext,
|
||||
AlgorithmSuite $algorithmSuite,
|
||||
array $options,
|
||||
MaterialsProviderV3 $provider,
|
||||
MetadataEnvelope $envelope
|
||||
): AppendStream;
|
||||
|
||||
/**
|
||||
* Dependency to provide an interface for building a decryption stream for
|
||||
* cipher text given metadata and materials to do so.
|
||||
*
|
||||
* @param string $cipherText Plain-text data to be decrypted using the
|
||||
* materials, algorithm, and data provided.
|
||||
* @param MaterialsProviderInterface $provider A provider to supply and encrypt
|
||||
* materials used in encryption.
|
||||
* @param MetadataEnvelope $envelope A storage envelope for encryption
|
||||
* metadata to be read from.
|
||||
* @param string $commitmentPolicy Commitment Policy to use for decrypting objects.
|
||||
* @param array $options Options used for decryption.
|
||||
*
|
||||
* @return AesStreamInterface
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
abstract public function decrypt(
|
||||
string $cipherText,
|
||||
MaterialsProviderInterfaceV3 $provider,
|
||||
MetadataEnvelope $envelope,
|
||||
string $commitmentPolicy,
|
||||
array $options = []
|
||||
): AesStreamInterface;
|
||||
}
|
||||
146
vendor/aws/aws-sdk-php/src/Crypto/AesDecryptingStream.php
vendored
Normal file
146
vendor/aws/aws-sdk-php/src/Crypto/AesDecryptingStream.php
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
namespace Aws\Crypto;
|
||||
|
||||
use GuzzleHttp\Psr7\StreamDecoratorTrait;
|
||||
use \LogicException;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
use Aws\Crypto\Cipher\CipherMethod;
|
||||
|
||||
/**
|
||||
* @internal Represents a stream of data to be decrypted with passed cipher.
|
||||
*/
|
||||
class AesDecryptingStream implements AesStreamInterface
|
||||
{
|
||||
const BLOCK_SIZE = 16; // 128 bits
|
||||
|
||||
use StreamDecoratorTrait;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $buffer = '';
|
||||
|
||||
/**
|
||||
* @var CipherMethod
|
||||
*/
|
||||
private $cipherMethod;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $key;
|
||||
|
||||
/**
|
||||
* @var StreamInterface
|
||||
*/
|
||||
private $stream;
|
||||
|
||||
/**
|
||||
* @param StreamInterface $cipherText
|
||||
* @param string $key
|
||||
* @param CipherMethod $cipherMethod
|
||||
*/
|
||||
public function __construct(
|
||||
StreamInterface $cipherText,
|
||||
$key,
|
||||
CipherMethod $cipherMethod
|
||||
) {
|
||||
$this->stream = $cipherText;
|
||||
$this->key = $key;
|
||||
$this->cipherMethod = clone $cipherMethod;
|
||||
}
|
||||
|
||||
public function getOpenSslName()
|
||||
{
|
||||
return $this->cipherMethod->getOpenSslName();
|
||||
}
|
||||
|
||||
public function getAesName()
|
||||
{
|
||||
return $this->cipherMethod->getAesName();
|
||||
}
|
||||
|
||||
public function getCurrentIv()
|
||||
{
|
||||
return $this->cipherMethod->getCurrentIv();
|
||||
}
|
||||
|
||||
public function getSize(): ?int
|
||||
{
|
||||
$plainTextSize = $this->stream->getSize();
|
||||
|
||||
if ($this->cipherMethod->requiresPadding()) {
|
||||
// PKCS7 padding requires that between 1 and self::BLOCK_SIZE be
|
||||
// added to the plaintext to make it an even number of blocks. The
|
||||
// plaintext is between strlen($cipherText) - self::BLOCK_SIZE and
|
||||
// strlen($cipherText) - 1
|
||||
return null;
|
||||
}
|
||||
|
||||
return $plainTextSize;
|
||||
}
|
||||
|
||||
public function isWritable(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function read($length): string
|
||||
{
|
||||
if ($length > strlen($this->buffer)) {
|
||||
$this->buffer .= $this->decryptBlock(
|
||||
(int) (
|
||||
self::BLOCK_SIZE * ceil(($length - strlen($this->buffer)) / self::BLOCK_SIZE)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$data = substr($this->buffer, 0, $length);
|
||||
$this->buffer = substr($this->buffer, $length);
|
||||
|
||||
return $data ? $data : '';
|
||||
}
|
||||
|
||||
public function seek($offset, $whence = SEEK_SET): void
|
||||
{
|
||||
if ($offset === 0 && $whence === SEEK_SET) {
|
||||
$this->buffer = '';
|
||||
$this->cipherMethod->seek(0, SEEK_SET);
|
||||
$this->stream->seek(0, SEEK_SET);
|
||||
} else {
|
||||
throw new LogicException('AES encryption streams only support being'
|
||||
. ' rewound, not arbitrary seeking.');
|
||||
}
|
||||
}
|
||||
|
||||
private function decryptBlock($length)
|
||||
{
|
||||
if ($this->stream->eof()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$cipherText = '';
|
||||
do {
|
||||
$cipherText .= $this->stream->read((int) ($length - strlen($cipherText)));
|
||||
} while (strlen($cipherText) < $length && !$this->stream->eof());
|
||||
|
||||
$options = OPENSSL_RAW_DATA;
|
||||
if (!$this->stream->eof()
|
||||
&& $this->stream->getSize() !== $this->stream->tell()
|
||||
) {
|
||||
$options |= OPENSSL_ZERO_PADDING;
|
||||
}
|
||||
|
||||
$plaintext = openssl_decrypt(
|
||||
$cipherText,
|
||||
$this->cipherMethod->getOpenSslName(),
|
||||
$this->key,
|
||||
$options,
|
||||
$this->cipherMethod->getCurrentIv()
|
||||
);
|
||||
|
||||
$this->cipherMethod->update($cipherText);
|
||||
|
||||
return $plaintext;
|
||||
}
|
||||
}
|
||||
151
vendor/aws/aws-sdk-php/src/Crypto/AesEncryptingStream.php
vendored
Normal file
151
vendor/aws/aws-sdk-php/src/Crypto/AesEncryptingStream.php
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
namespace Aws\Crypto;
|
||||
|
||||
use GuzzleHttp\Psr7\StreamDecoratorTrait;
|
||||
use \LogicException;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
use Aws\Crypto\Cipher\CipherMethod;
|
||||
|
||||
/**
|
||||
* @internal Represents a stream of data to be encrypted with a passed cipher.
|
||||
*/
|
||||
class AesEncryptingStream implements AesStreamInterface
|
||||
{
|
||||
const BLOCK_SIZE = 16; // 128 bits
|
||||
|
||||
use StreamDecoratorTrait;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $buffer = '';
|
||||
|
||||
/**
|
||||
* @var CipherMethod
|
||||
*/
|
||||
private $cipherMethod;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $key;
|
||||
|
||||
/**
|
||||
* @var StreamInterface
|
||||
*/
|
||||
private $stream;
|
||||
|
||||
/**
|
||||
* @param StreamInterface $plainText
|
||||
* @param string $key
|
||||
* @param CipherMethod $cipherMethod
|
||||
*/
|
||||
public function __construct(
|
||||
StreamInterface $plainText,
|
||||
$key,
|
||||
CipherMethod $cipherMethod
|
||||
) {
|
||||
$this->stream = $plainText;
|
||||
$this->key = $key;
|
||||
$this->cipherMethod = clone $cipherMethod;
|
||||
}
|
||||
|
||||
public function getOpenSslName()
|
||||
{
|
||||
return $this->cipherMethod->getOpenSslName();
|
||||
}
|
||||
|
||||
public function getAesName()
|
||||
{
|
||||
return $this->cipherMethod->getAesName();
|
||||
}
|
||||
|
||||
public function getCurrentIv()
|
||||
{
|
||||
return $this->cipherMethod->getCurrentIv();
|
||||
}
|
||||
|
||||
public function getSize(): ?int
|
||||
{
|
||||
$plainTextSize = $this->stream->getSize();
|
||||
|
||||
if ($this->cipherMethod->requiresPadding() && $plainTextSize !== null) {
|
||||
// PKCS7 padding requires that between 1 and self::BLOCK_SIZE be
|
||||
// added to the plaintext to make it an even number of blocks.
|
||||
$padding = self::BLOCK_SIZE - $plainTextSize % self::BLOCK_SIZE;
|
||||
return $plainTextSize + $padding;
|
||||
}
|
||||
|
||||
return $plainTextSize;
|
||||
}
|
||||
|
||||
public function isWritable(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function read($length): string
|
||||
{
|
||||
if ($length > strlen($this->buffer)) {
|
||||
$this->buffer .= $this->encryptBlock(
|
||||
(int)
|
||||
self::BLOCK_SIZE * ceil(($length - strlen($this->buffer)) / self::BLOCK_SIZE)
|
||||
);
|
||||
}
|
||||
|
||||
$data = substr($this->buffer, 0, $length);
|
||||
$this->buffer = substr($this->buffer, $length);
|
||||
|
||||
return $data ? $data : '';
|
||||
}
|
||||
|
||||
public function seek($offset, $whence = SEEK_SET): void
|
||||
{
|
||||
if ($whence === SEEK_CUR) {
|
||||
$offset = $this->tell() + $offset;
|
||||
$whence = SEEK_SET;
|
||||
}
|
||||
|
||||
if ($whence === SEEK_SET) {
|
||||
$this->buffer = '';
|
||||
$wholeBlockOffset
|
||||
= (int) ($offset / self::BLOCK_SIZE) * self::BLOCK_SIZE;
|
||||
$this->stream->seek($wholeBlockOffset);
|
||||
$this->cipherMethod->seek($wholeBlockOffset);
|
||||
$this->read($offset - $wholeBlockOffset);
|
||||
} else {
|
||||
throw new LogicException('Unrecognized whence.');
|
||||
}
|
||||
}
|
||||
|
||||
private function encryptBlock($length)
|
||||
{
|
||||
if ($this->stream->eof()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$plainText = '';
|
||||
do {
|
||||
$plainText .= $this->stream->read((int) ($length - strlen($plainText)));
|
||||
} while (strlen($plainText) < $length && !$this->stream->eof());
|
||||
|
||||
$options = OPENSSL_RAW_DATA;
|
||||
if (!$this->stream->eof()
|
||||
|| $this->stream->getSize() !== $this->stream->tell()
|
||||
) {
|
||||
$options |= OPENSSL_ZERO_PADDING;
|
||||
}
|
||||
|
||||
$cipherText = openssl_encrypt(
|
||||
$plainText,
|
||||
$this->cipherMethod->getOpenSslName(),
|
||||
$this->key,
|
||||
$options,
|
||||
$this->cipherMethod->getCurrentIv()
|
||||
);
|
||||
|
||||
$this->cipherMethod->update($cipherText);
|
||||
|
||||
return $cipherText;
|
||||
}
|
||||
}
|
||||
104
vendor/aws/aws-sdk-php/src/Crypto/AesGcmDecryptingStream.php
vendored
Normal file
104
vendor/aws/aws-sdk-php/src/Crypto/AesGcmDecryptingStream.php
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
namespace Aws\Crypto;
|
||||
|
||||
use Aws\Exception\CryptoException;
|
||||
use GuzzleHttp\Psr7;
|
||||
use GuzzleHttp\Psr7\StreamDecoratorTrait;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
/**
|
||||
* @internal Represents a stream of data to be gcm decrypted.
|
||||
*/
|
||||
class AesGcmDecryptingStream implements AesStreamInterface
|
||||
{
|
||||
use StreamDecoratorTrait;
|
||||
|
||||
private $aad;
|
||||
|
||||
private $initializationVector;
|
||||
|
||||
private $key;
|
||||
|
||||
private $keySize;
|
||||
|
||||
private $cipherText;
|
||||
|
||||
private $tag;
|
||||
|
||||
private $tagLength;
|
||||
|
||||
/**
|
||||
* @var StreamInterface
|
||||
*/
|
||||
private $stream;
|
||||
|
||||
/**
|
||||
* @param StreamInterface $cipherText
|
||||
* @param string $key
|
||||
* @param string $initializationVector
|
||||
* @param string $tag
|
||||
* @param string $aad
|
||||
* @param int $tagLength
|
||||
* @param int $keySize
|
||||
*/
|
||||
public function __construct(
|
||||
StreamInterface $cipherText,
|
||||
$key,
|
||||
$initializationVector,
|
||||
$tag,
|
||||
$aad = '',
|
||||
$tagLength = 128,
|
||||
$keySize = 256
|
||||
) {
|
||||
$this->cipherText = $cipherText;
|
||||
$this->key = $key;
|
||||
$this->initializationVector = $initializationVector;
|
||||
$this->tag = $tag;
|
||||
$this->aad = $aad;
|
||||
$this->tagLength = $tagLength;
|
||||
$this->keySize = $keySize;
|
||||
// unsetting the property forces the first access to go through
|
||||
// __get().
|
||||
unset($this->stream);
|
||||
}
|
||||
|
||||
public function getOpenSslName()
|
||||
{
|
||||
return "aes-{$this->keySize}-gcm";
|
||||
}
|
||||
|
||||
public function getAesName()
|
||||
{
|
||||
return 'AES/GCM/NoPadding';
|
||||
}
|
||||
|
||||
public function getCurrentIv()
|
||||
{
|
||||
return $this->initializationVector;
|
||||
}
|
||||
|
||||
public function createStream()
|
||||
{
|
||||
|
||||
$result = \openssl_decrypt(
|
||||
(string)$this->cipherText,
|
||||
$this->getOpenSslName(),
|
||||
$this->key,
|
||||
OPENSSL_RAW_DATA,
|
||||
$this->initializationVector,
|
||||
$this->tag,
|
||||
$this->aad
|
||||
);
|
||||
if ($result === false) {
|
||||
throw new CryptoException('The requested object could not be '
|
||||
. 'decrypted due to an invalid authentication tag.');
|
||||
}
|
||||
return Psr7\Utils::streamFor($result);
|
||||
|
||||
}
|
||||
|
||||
public function isWritable(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
119
vendor/aws/aws-sdk-php/src/Crypto/AesGcmEncryptingStream.php
vendored
Normal file
119
vendor/aws/aws-sdk-php/src/Crypto/AesGcmEncryptingStream.php
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
namespace Aws\Crypto;
|
||||
|
||||
use GuzzleHttp\Psr7;
|
||||
use GuzzleHttp\Psr7\StreamDecoratorTrait;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
/**
|
||||
* @internal Represents a stream of data to be gcm encrypted.
|
||||
*/
|
||||
class AesGcmEncryptingStream implements AesStreamInterface, AesStreamInterfaceV2
|
||||
{
|
||||
use StreamDecoratorTrait;
|
||||
|
||||
private $aad;
|
||||
|
||||
private $initializationVector;
|
||||
|
||||
private $key;
|
||||
|
||||
private $keySize;
|
||||
|
||||
private $plaintext;
|
||||
|
||||
private $tag = '';
|
||||
|
||||
private $tagLength;
|
||||
|
||||
/**
|
||||
* @var StreamInterface
|
||||
*/
|
||||
private $stream;
|
||||
|
||||
/**
|
||||
* Same as non-static 'getAesName' method, allowing calls in a static
|
||||
* context.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getStaticAesName()
|
||||
{
|
||||
return 'AES/GCM/NoPadding';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param StreamInterface $plaintext
|
||||
* @param string $key
|
||||
* @param string $initializationVector
|
||||
* @param string $aad
|
||||
* @param int $tagLength
|
||||
* @param int $keySize
|
||||
*/
|
||||
public function __construct(
|
||||
StreamInterface $plaintext,
|
||||
$key,
|
||||
$initializationVector,
|
||||
$aad = '',
|
||||
$tagLength = 16,
|
||||
$keySize = 256
|
||||
) {
|
||||
|
||||
$this->plaintext = $plaintext;
|
||||
$this->key = $key;
|
||||
$this->initializationVector = $initializationVector;
|
||||
$this->aad = $aad;
|
||||
$this->tagLength = $tagLength;
|
||||
$this->keySize = $keySize;
|
||||
// unsetting the property forces the first access to go through
|
||||
// __get().
|
||||
unset($this->stream);
|
||||
}
|
||||
|
||||
public function getOpenSslName()
|
||||
{
|
||||
return "aes-{$this->keySize}-gcm";
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as static method and retained for backwards compatibility
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAesName()
|
||||
{
|
||||
return self::getStaticAesName();
|
||||
}
|
||||
|
||||
public function getCurrentIv()
|
||||
{
|
||||
return $this->initializationVector;
|
||||
}
|
||||
|
||||
public function createStream()
|
||||
{
|
||||
return Psr7\Utils::streamFor(\openssl_encrypt(
|
||||
(string)$this->plaintext,
|
||||
$this->getOpenSslName(),
|
||||
$this->key,
|
||||
OPENSSL_RAW_DATA,
|
||||
$this->initializationVector,
|
||||
$this->tag,
|
||||
$this->aad,
|
||||
$this->tagLength
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getTag()
|
||||
{
|
||||
return $this->tag;
|
||||
}
|
||||
|
||||
public function isWritable(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
30
vendor/aws/aws-sdk-php/src/Crypto/AesStreamInterface.php
vendored
Normal file
30
vendor/aws/aws-sdk-php/src/Crypto/AesStreamInterface.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
namespace Aws\Crypto;
|
||||
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
interface AesStreamInterface extends StreamInterface
|
||||
{
|
||||
/**
|
||||
* Returns an identifier recognizable by `openssl_*` functions, such as
|
||||
* `aes-256-cbc` or `aes-128-ctr`.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getOpenSslName();
|
||||
|
||||
/**
|
||||
* Returns an AES recognizable name, such as 'AES/GCM/NoPadding'.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAesName();
|
||||
|
||||
/**
|
||||
* Returns the IV that should be used to initialize the next block in
|
||||
* encrypt or decrypt.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCurrentIv();
|
||||
}
|
||||
31
vendor/aws/aws-sdk-php/src/Crypto/AesStreamInterfaceV2.php
vendored
Normal file
31
vendor/aws/aws-sdk-php/src/Crypto/AesStreamInterfaceV2.php
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
namespace Aws\Crypto;
|
||||
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
interface AesStreamInterfaceV2 extends StreamInterface
|
||||
{
|
||||
/**
|
||||
* Returns an AES recognizable name, such as 'AES/GCM/NoPadding'. V2
|
||||
* interface is accessible from a static context.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getStaticAesName();
|
||||
|
||||
/**
|
||||
* Returns an identifier recognizable by `openssl_*` functions, such as
|
||||
* `aes-256-cbc` or `aes-128-ctr`.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getOpenSslName();
|
||||
|
||||
/**
|
||||
* Returns the IV that should be used to initialize the next block in
|
||||
* encrypt or decrypt.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCurrentIv();
|
||||
}
|
||||
26
vendor/aws/aws-sdk-php/src/Crypto/AlgorithmConstants.php
vendored
Normal file
26
vendor/aws/aws-sdk-php/src/Crypto/AlgorithmConstants.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
namespace Aws\Crypto;
|
||||
|
||||
class AlgorithmConstants
|
||||
{
|
||||
/**
|
||||
* The maximum number of 16-byte blocks that can be encrypted with a
|
||||
* GCM cipher. Note the maximum bit-length of the plaintext is (2^39 - 256),
|
||||
* which translates to a maximum byte-length of (2^36 - 32), which in turn
|
||||
* translates to a maximum block-length of (2^32 - 2).
|
||||
*
|
||||
* Reference: NIST Special Publication 800-38D.
|
||||
* @link http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
|
||||
*/
|
||||
public const GCM_MAX_CONTENT_LENGTH_BITS = (1 << 39) - 256;
|
||||
|
||||
/**
|
||||
* The Maximum length of the content that can be encrypted in CBC mode.
|
||||
*/
|
||||
public const CBC_MAX_CONTENT_LENGTH_BYTES = 1 << 55;
|
||||
|
||||
/**
|
||||
* The maximum number of bytes that can be securely encrypted per a single key using AES/CTR.
|
||||
*/
|
||||
public const CTR_MAX_CONTENT_LENGTH_BYTES = -1;
|
||||
}
|
||||
227
vendor/aws/aws-sdk-php/src/Crypto/AlgorithmSuite.php
vendored
Normal file
227
vendor/aws/aws-sdk-php/src/Crypto/AlgorithmSuite.php
vendored
Normal file
@@ -0,0 +1,227 @@
|
||||
<?php
|
||||
namespace Aws\Crypto;
|
||||
|
||||
use Aws\S3\Crypto\S3EncryptionClientV3;
|
||||
|
||||
enum AlgorithmSuite: int
|
||||
{
|
||||
case ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY = 0x0073;
|
||||
case ALG_AES_256_GCM_IV12_TAG16_NO_KDF = 0x0072;
|
||||
case ALG_AES_256_CBC_IV16_NO_KDF = 0x0070;
|
||||
|
||||
public function getId(): int
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
public function isLegacy(): bool
|
||||
{
|
||||
return match ($this) {
|
||||
self::ALG_AES_256_CBC_IV16_NO_KDF => true,
|
||||
default => false,
|
||||
};
|
||||
}
|
||||
|
||||
public function isKeyCommitting(): bool
|
||||
{
|
||||
return match ($this) {
|
||||
self::ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY => true,
|
||||
default => false,
|
||||
};
|
||||
}
|
||||
|
||||
public function getDataKeyAlgorithm(): string
|
||||
{
|
||||
return match ($this) {
|
||||
self::ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY,
|
||||
self::ALG_AES_256_GCM_IV12_TAG16_NO_KDF,
|
||||
self::ALG_AES_256_CBC_IV16_NO_KDF => "AES",
|
||||
};
|
||||
}
|
||||
|
||||
public function getDataKeyLengthBits(): string
|
||||
{
|
||||
return match ($this) {
|
||||
self::ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY,
|
||||
self::ALG_AES_256_GCM_IV12_TAG16_NO_KDF,
|
||||
self::ALG_AES_256_CBC_IV16_NO_KDF => "256",
|
||||
};
|
||||
}
|
||||
|
||||
public function getCipherName(): string
|
||||
{
|
||||
return match ($this) {
|
||||
self::ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY,
|
||||
self::ALG_AES_256_GCM_IV12_TAG16_NO_KDF => "gcm",
|
||||
self::ALG_AES_256_CBC_IV16_NO_KDF => "cbc",
|
||||
};
|
||||
}
|
||||
|
||||
public function getCipherBlockSizeBits(): int
|
||||
{
|
||||
return match ($this) {
|
||||
self::ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY,
|
||||
self::ALG_AES_256_GCM_IV12_TAG16_NO_KDF,
|
||||
self::ALG_AES_256_CBC_IV16_NO_KDF => 128,
|
||||
};
|
||||
}
|
||||
|
||||
public function getCipherBlockSizeBytes(): int
|
||||
{
|
||||
return $this->getCipherBlockSizeBits() / 8;
|
||||
}
|
||||
|
||||
public function getIvLengthBits(): int
|
||||
{
|
||||
return match ($this) {
|
||||
self::ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY,
|
||||
self::ALG_AES_256_GCM_IV12_TAG16_NO_KDF => 96,
|
||||
self::ALG_AES_256_CBC_IV16_NO_KDF => 128,
|
||||
};
|
||||
}
|
||||
|
||||
public function getIvLengthBytes(): int
|
||||
{
|
||||
return $this->getIvLengthBits() / 8;
|
||||
}
|
||||
|
||||
public function getCipherTagLengthBits(): int
|
||||
{
|
||||
return match ($this) {
|
||||
self::ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY,
|
||||
self::ALG_AES_256_GCM_IV12_TAG16_NO_KDF => 128,
|
||||
self::ALG_AES_256_CBC_IV16_NO_KDF => 0,
|
||||
};
|
||||
}
|
||||
|
||||
public function getCipherTagLengthInBytes(): int
|
||||
{
|
||||
return $this->getCipherTagLengthBits() / 8;
|
||||
}
|
||||
|
||||
public function getCipherMaxContentLengthBits(): int
|
||||
{
|
||||
return match ($this) {
|
||||
self::ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY,
|
||||
self::ALG_AES_256_GCM_IV12_TAG16_NO_KDF => AlgorithmConstants::GCM_MAX_CONTENT_LENGTH_BITS,
|
||||
self::ALG_AES_256_CBC_IV16_NO_KDF => AlgorithmConstants::CBC_MAX_CONTENT_LENGTH_BYTES,
|
||||
};
|
||||
}
|
||||
|
||||
public function getCipherMaxContentLengthBytes(): int
|
||||
{
|
||||
return $this->getCipherMaxContentLengthBits() / 8;
|
||||
}
|
||||
|
||||
public function getHashingAlgorithm(): string
|
||||
{
|
||||
return match ($this) {
|
||||
self::ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY => "sha512",
|
||||
default => "",
|
||||
};
|
||||
}
|
||||
|
||||
public function getDerivationInputKeyLengthBits(): int
|
||||
{
|
||||
return match ($this) {
|
||||
self::ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY => 256,
|
||||
default => 0,
|
||||
};
|
||||
}
|
||||
|
||||
public function getDerivationInputKeyLengthBytes(): int
|
||||
{
|
||||
return $this->getDerivationInputKeyLengthBits() / 8;
|
||||
}
|
||||
|
||||
public function getDerivationOutputKeyLengthBits(): int
|
||||
{
|
||||
return match ($this) {
|
||||
self::ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY => 256,
|
||||
default => 0,
|
||||
};
|
||||
}
|
||||
|
||||
public function getDerivationOutputKeyLengthBytes(): int
|
||||
{
|
||||
return $this->getDerivationOutputKeyLengthBits() / 8;
|
||||
}
|
||||
|
||||
public function getCommitmentInputKeyLengthBits(): int
|
||||
{
|
||||
return match ($this) {
|
||||
self::ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY => 256,
|
||||
default => 0,
|
||||
};
|
||||
}
|
||||
|
||||
public function getCommitmentInputKeyLengthBytes(): int
|
||||
{
|
||||
return $this->getCommitmentInputKeyLengthBits() / 8;
|
||||
}
|
||||
|
||||
public function getCommitmentOutputKeyLengthBits(): int
|
||||
{
|
||||
return match ($this) {
|
||||
self::ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY => 224,
|
||||
default => 0,
|
||||
};
|
||||
}
|
||||
|
||||
public function getCommitmentOutputKeyLengthBytes(): int
|
||||
{
|
||||
return $this->getCommitmentOutputKeyLengthBits() / 8;
|
||||
}
|
||||
|
||||
public function getKeyCommitmentSaltLengthBits(): int
|
||||
{
|
||||
return match ($this) {
|
||||
self::ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY => 224,
|
||||
default => 0,
|
||||
};
|
||||
}
|
||||
|
||||
//= ../specification/s3-encryption/client.md#key-commitment
|
||||
//# The S3EC MUST validate the configured Encryption Algorithm against the provided key commitment policy.
|
||||
public static function validateCommitmentPolicyOnEncrypt(
|
||||
array $cipherOptions,
|
||||
string $keyCommitmentPolicy
|
||||
): self {
|
||||
$cipherOptions['Cipher'] = strtolower($cipherOptions['Cipher']);
|
||||
//= ../specification/s3-encryption/client.md#encryption-algorithm
|
||||
//# The S3EC MUST validate that the configured encryption algorithm is not legacy.
|
||||
if (!S3EncryptionClientV3::isSupportedCipher($cipherOptions['Cipher'])) {
|
||||
//= ../specification/s3-encryption/client.md#encryption-algorithm
|
||||
//# If the configured encryption algorithm is legacy, then the S3EC MUST throw an exception.
|
||||
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 (!MaterialsProviderV3::isSupportedKeySize($cipherOptions['KeySize'])) {
|
||||
throw new \InvalidArgumentException('The cipher "KeySize" requested'
|
||||
. ' is not supported by AES (256).');
|
||||
}
|
||||
|
||||
//= ../specification/s3-encryption/key-commitment.md#commitment-policy
|
||||
//# When the commitment policy is FORBID_ENCRYPT_ALLOW_DECRYPT, the S3EC MUST NOT encrypt using an algorithm suite which supports key commitment.
|
||||
if ($keyCommitmentPolicy === 'FORBID_ENCRYPT_ALLOW_DECRYPT') {
|
||||
return self::ALG_AES_256_GCM_IV12_TAG16_NO_KDF;
|
||||
} else {
|
||||
//= ../specification/s3-encryption/key-commitment.md#commitment-policy
|
||||
//# When the commitment policy is REQUIRE_ENCRYPT_ALLOW_DECRYPT, the S3EC MUST only encrypt using an algorithm suite which supports key commitment.
|
||||
|
||||
//= ../specification/s3-encryption/key-commitment.md#commitment-policy
|
||||
//# When the commitment policy is REQUIRE_ENCRYPT_REQUIRE_DECRYPT, the S3EC MUST only encrypt using an algorithm suite which supports key commitment.
|
||||
return self::ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY;
|
||||
}
|
||||
}
|
||||
}
|
||||
88
vendor/aws/aws-sdk-php/src/Crypto/Cipher/Cbc.php
vendored
Normal file
88
vendor/aws/aws-sdk-php/src/Crypto/Cipher/Cbc.php
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
namespace Aws\Crypto\Cipher;
|
||||
|
||||
use \InvalidArgumentException;
|
||||
use \LogicException;
|
||||
|
||||
/**
|
||||
* An implementation of the CBC cipher for use with an AesEncryptingStream or
|
||||
* AesDecrypting stream.
|
||||
*
|
||||
* This cipher method is deprecated and in maintenance mode - no new updates will be
|
||||
* released. Please see https://docs.aws.amazon.com/general/latest/gr/aws_sdk_cryptography.html
|
||||
* for more information.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
class Cbc implements CipherMethod
|
||||
{
|
||||
const BLOCK_SIZE = 16;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $baseIv;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $iv;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $keySize;
|
||||
|
||||
/**
|
||||
* @param string $iv Base Initialization Vector for the cipher.
|
||||
* @param int $keySize Size of the encryption key, in bits, that will be
|
||||
* used.
|
||||
*
|
||||
* @throws InvalidArgumentException Thrown if the passed iv does not match
|
||||
* the iv length required by the cipher.
|
||||
*/
|
||||
public function __construct($iv, $keySize = 256)
|
||||
{
|
||||
$this->baseIv = $this->iv = $iv;
|
||||
$this->keySize = $keySize;
|
||||
|
||||
if (strlen($iv) !== openssl_cipher_iv_length($this->getOpenSslName())) {
|
||||
throw new InvalidArgumentException('Invalid initialization vector');
|
||||
}
|
||||
}
|
||||
|
||||
public function getOpenSslName()
|
||||
{
|
||||
return "aes-{$this->keySize}-cbc";
|
||||
}
|
||||
|
||||
public function getAesName()
|
||||
{
|
||||
return 'AES/CBC/PKCS5Padding';
|
||||
}
|
||||
|
||||
public function getCurrentIv()
|
||||
{
|
||||
return $this->iv;
|
||||
}
|
||||
|
||||
public function requiresPadding()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function seek($offset, $whence = SEEK_SET)
|
||||
{
|
||||
if ($offset === 0 && $whence === SEEK_SET) {
|
||||
$this->iv = $this->baseIv;
|
||||
} else {
|
||||
throw new LogicException('CBC initialization only support being'
|
||||
. ' rewound, not arbitrary seeking.');
|
||||
}
|
||||
}
|
||||
|
||||
public function update($cipherTextBlock)
|
||||
{
|
||||
$this->iv = substr($cipherTextBlock, self::BLOCK_SIZE * -1);
|
||||
}
|
||||
}
|
||||
72
vendor/aws/aws-sdk-php/src/Crypto/Cipher/CipherBuilderTrait.php
vendored
Normal file
72
vendor/aws/aws-sdk-php/src/Crypto/Cipher/CipherBuilderTrait.php
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
namespace Aws\Crypto\Cipher;
|
||||
|
||||
use Aws\Exception\CryptoException;
|
||||
|
||||
trait CipherBuilderTrait
|
||||
{
|
||||
/**
|
||||
* Returns an identifier recognizable by `openssl_*` functions, such as
|
||||
* `aes-256-cbc` or `aes-128-ctr`.
|
||||
*
|
||||
* @param string $cipherName Name of the cipher being used for encrypting
|
||||
* or decrypting.
|
||||
* @param int $keySize Size of the encryption key, in bits, that will be
|
||||
* used.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getCipherOpenSslName($cipherName, $keySize)
|
||||
{
|
||||
return "aes-{$keySize}-{$cipherName}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a CipherMethod for the given name, initialized with the other
|
||||
* data passed for use in encrypting or decrypting.
|
||||
*
|
||||
* @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 CipherMethod
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
protected function buildCipherMethod($cipherName, $iv, $keySize)
|
||||
{
|
||||
switch ($cipherName) {
|
||||
case 'cbc':
|
||||
return new Cbc(
|
||||
$iv,
|
||||
$keySize
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a reverse lookup to get the openssl_* cipher name from the
|
||||
* AESName passed in from the MetadataEnvelope.
|
||||
*
|
||||
* @param $aesName
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
protected function getCipherFromAesName($aesName)
|
||||
{
|
||||
switch ($aesName) {
|
||||
case 'AES/GCM/NoPadding':
|
||||
return 'gcm';
|
||||
case 'AES/CBC/PKCS5Padding':
|
||||
return 'cbc';
|
||||
default:
|
||||
throw new CryptoException('Unrecognized or unsupported'
|
||||
. ' AESName for reverse lookup.');
|
||||
}
|
||||
}
|
||||
}
|
||||
59
vendor/aws/aws-sdk-php/src/Crypto/Cipher/CipherMethod.php
vendored
Normal file
59
vendor/aws/aws-sdk-php/src/Crypto/Cipher/CipherMethod.php
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
namespace Aws\Crypto\Cipher;
|
||||
|
||||
interface CipherMethod
|
||||
{
|
||||
/**
|
||||
* Returns an identifier recognizable by `openssl_*` functions, such as
|
||||
* `aes-256-cbc` or `aes-128-ctr`.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getOpenSslName();
|
||||
|
||||
/**
|
||||
* Returns an AES recognizable name, such as 'AES/GCM/NoPadding'.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAesName();
|
||||
|
||||
/**
|
||||
* Returns the IV that should be used to initialize the next block in
|
||||
* encrypt or decrypt.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCurrentIv();
|
||||
|
||||
/**
|
||||
* Indicates whether the cipher method used with this IV requires padding
|
||||
* the final block to make sure the plaintext is evenly divisible by the
|
||||
* block size.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function requiresPadding();
|
||||
|
||||
/**
|
||||
* Adjust the return of this::getCurrentIv to reflect a seek performed on
|
||||
* the encryption stream using this IV object.
|
||||
*
|
||||
* @param int $offset
|
||||
* @param int $whence
|
||||
*
|
||||
* @throws LogicException Thrown if the requested seek is not supported by
|
||||
* this IV implementation. For example, a CBC IV
|
||||
* only supports a full rewind ($offset === 0 &&
|
||||
* $whence === SEEK_SET)
|
||||
*/
|
||||
public function seek($offset, $whence = SEEK_SET);
|
||||
|
||||
/**
|
||||
* Take account of the last cipher text block to adjust the return of
|
||||
* this::getCurrentIv
|
||||
*
|
||||
* @param string $cipherTextBlock
|
||||
*/
|
||||
public function update($cipherTextBlock);
|
||||
}
|
||||
181
vendor/aws/aws-sdk-php/src/Crypto/DecryptionTrait.php
vendored
Normal file
181
vendor/aws/aws-sdk-php/src/Crypto/DecryptionTrait.php
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
<?php
|
||||
namespace Aws\Crypto;
|
||||
|
||||
use GuzzleHttp\Psr7;
|
||||
use GuzzleHttp\Psr7\LimitStream;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
trait DecryptionTrait
|
||||
{
|
||||
/**
|
||||
* Dependency to reverse lookup the openssl_* cipher name from the AESName
|
||||
* in the MetadataEnvelope.
|
||||
*
|
||||
* @param $aesName
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
abstract protected function getCipherFromAesName($aesName);
|
||||
|
||||
/**
|
||||
* Dependency to generate a CipherMethod from a set of inputs for loading
|
||||
* in to an AesDecryptingStream.
|
||||
*
|
||||
* @param string $cipherName Name of the cipher to generate for decrypting.
|
||||
* @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 using cipher options loaded from the
|
||||
* MetadataEnvelope and MaterialsProvider. Can decrypt data from both the
|
||||
* legacy and V2 encryption client workflows.
|
||||
*
|
||||
* @param string $cipherText Plain-text data to be encrypted using the
|
||||
* materials, algorithm, and data provided.
|
||||
* @param MaterialsProviderInterface $provider A provider to supply and encrypt
|
||||
* materials used in encryption.
|
||||
* @param MetadataEnvelope $envelope A storage envelope for encryption
|
||||
* metadata to be read from.
|
||||
* @param array $cipherOptions Additional verification options.
|
||||
*
|
||||
* @return AesStreamInterface
|
||||
*
|
||||
* @throws \InvalidArgumentException Thrown when a value in $cipherOptions
|
||||
* is not valid.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function decrypt(
|
||||
$cipherText,
|
||||
MaterialsProviderInterface $provider,
|
||||
MetadataEnvelope $envelope,
|
||||
array $cipherOptions = []
|
||||
) {
|
||||
$cipherOptions['Iv'] = base64_decode(
|
||||
$envelope[MetadataEnvelope::IV_HEADER]
|
||||
);
|
||||
|
||||
$cipherOptions['TagLength'] =
|
||||
$envelope[MetadataEnvelope::CRYPTO_TAG_LENGTH_HEADER] / 8;
|
||||
|
||||
$cek = $provider->decryptCek(
|
||||
base64_decode(
|
||||
$envelope[MetadataEnvelope::CONTENT_KEY_V2_HEADER]
|
||||
),
|
||||
json_decode(
|
||||
$envelope[MetadataEnvelope::MATERIALS_DESCRIPTION_HEADER],
|
||||
true
|
||||
)
|
||||
);
|
||||
$cipherOptions['KeySize'] = strlen($cek) * 8;
|
||||
$cipherOptions['Cipher'] = $this->getCipherFromAesName(
|
||||
$envelope[MetadataEnvelope::CONTENT_CRYPTO_SCHEME_HEADER]
|
||||
);
|
||||
|
||||
$decryptionStream = $this->getDecryptingStream(
|
||||
$cipherText,
|
||||
$cek,
|
||||
$cipherOptions
|
||||
);
|
||||
unset($cek);
|
||||
|
||||
return $decryptionStream;
|
||||
}
|
||||
|
||||
private function getTagFromCiphertextStream(
|
||||
StreamInterface $cipherText,
|
||||
$tagLength
|
||||
) {
|
||||
$cipherTextSize = $cipherText->getSize();
|
||||
if ($cipherTextSize == null || $cipherTextSize <= 0) {
|
||||
throw new \RuntimeException('Cannot decrypt a stream of unknown'
|
||||
. ' size.');
|
||||
}
|
||||
return (string) new LimitStream(
|
||||
$cipherText,
|
||||
$tagLength,
|
||||
$cipherTextSize - $tagLength
|
||||
);
|
||||
}
|
||||
|
||||
private function getStrippedCiphertextStream(
|
||||
StreamInterface $cipherText,
|
||||
$tagLength
|
||||
) {
|
||||
$cipherTextSize = $cipherText->getSize();
|
||||
if ($cipherTextSize == null || $cipherTextSize <= 0) {
|
||||
throw new \RuntimeException('Cannot decrypt a stream of unknown'
|
||||
. ' size.');
|
||||
}
|
||||
return new LimitStream(
|
||||
$cipherText,
|
||||
$cipherTextSize - $tagLength,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a stream that wraps the cipher text with the proper cipher and
|
||||
* uses the content encryption key (CEK) to decrypt the data when read.
|
||||
*
|
||||
* @param string $cipherText 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
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
protected function getDecryptingStream(
|
||||
$cipherText,
|
||||
$cek,
|
||||
$cipherOptions
|
||||
) {
|
||||
$cipherTextStream = Psr7\Utils::streamFor($cipherText);
|
||||
switch ($cipherOptions['Cipher']) {
|
||||
case 'gcm':
|
||||
$cipherOptions['Tag'] = $this->getTagFromCiphertextStream(
|
||||
$cipherTextStream,
|
||||
$cipherOptions['TagLength']
|
||||
);
|
||||
|
||||
return new AesGcmDecryptingStream(
|
||||
$this->getStrippedCiphertextStream(
|
||||
$cipherTextStream,
|
||||
$cipherOptions['TagLength']
|
||||
),
|
||||
$cek,
|
||||
$cipherOptions['Iv'],
|
||||
$cipherOptions['Tag'],
|
||||
$cipherOptions['Aad'] = isset($cipherOptions['Aad'])
|
||||
? $cipherOptions['Aad']
|
||||
: '',
|
||||
$cipherOptions['TagLength'] ?: null,
|
||||
$cipherOptions['KeySize']
|
||||
);
|
||||
default:
|
||||
$cipherMethod = $this->buildCipherMethod(
|
||||
$cipherOptions['Cipher'],
|
||||
$cipherOptions['Iv'],
|
||||
$cipherOptions['KeySize']
|
||||
);
|
||||
return new AesDecryptingStream(
|
||||
$cipherTextStream,
|
||||
$cek,
|
||||
$cipherMethod
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
424
vendor/aws/aws-sdk-php/src/Crypto/DecryptionTraitV2.php
vendored
Normal file
424
vendor/aws/aws-sdk-php/src/Crypto/DecryptionTraitV2.php
vendored
Normal file
@@ -0,0 +1,424 @@
|
||||
<?php
|
||||
namespace Aws\Crypto;
|
||||
|
||||
use Aws\Exception\CryptoException;
|
||||
use GuzzleHttp\Psr7;
|
||||
use GuzzleHttp\Psr7\LimitStream;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
trait DecryptionTraitV2
|
||||
{
|
||||
/**
|
||||
* Dependency to reverse lookup the openssl_* cipher name from the AESName
|
||||
* in the MetadataEnvelope.
|
||||
*
|
||||
* @param $aesName
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
abstract protected function getCipherFromAesName($aesName);
|
||||
|
||||
/**
|
||||
* Dependency to generate a CipherMethod from a set of inputs for loading
|
||||
* in to an AesDecryptingStream.
|
||||
*
|
||||
* @param string $cipherName Name of the cipher to generate for decrypting.
|
||||
* @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 using cipher options loaded from the
|
||||
* MetadataEnvelope and MaterialsProvider. Can decrypt data from both the
|
||||
* legacy and V2 encryption client workflows.
|
||||
*
|
||||
* @param string $cipherText Plain-text data to be encrypted using the
|
||||
* materials, algorithm, and data provided.
|
||||
* @param MaterialsProviderInterfaceV2 $provider A provider to supply and encrypt
|
||||
* materials used in encryption.
|
||||
* @param MetadataEnvelope $envelope A storage envelope for encryption
|
||||
* metadata to be read from.
|
||||
* @param array $options Options used for decryption.
|
||||
*
|
||||
* @return AesStreamInterface
|
||||
*
|
||||
* @throws \InvalidArgumentException Thrown when a value in $cipherOptions
|
||||
* is not valid.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function decrypt(
|
||||
$cipherText,
|
||||
MaterialsProviderInterfaceV2 $provider,
|
||||
MetadataEnvelope $envelope,
|
||||
array $options = []
|
||||
)
|
||||
{
|
||||
$commitmentPolicy = $this->getKeyCommitmentPolicy($options);
|
||||
unset($options['@CommitmentPolicy']);
|
||||
if (isset($envelope[MetadataEnvelope::ENCRYPTED_DATA_KEY_V3])) {
|
||||
if ($commitmentPolicy !== "FORBID_ENCRYPT_ALLOW_DECRYPT") {
|
||||
throw new CryptoException(
|
||||
"The requested item is encrypted"
|
||||
. " with Key Commitment. The current policy {$commitmentPolicy}"
|
||||
. " conflicts with the object metadata. Select an appropriate"
|
||||
. " '@CommitmentPolicy' to decrypt this item."
|
||||
);
|
||||
}
|
||||
$algorithmSuite = AlgorithmSuite::ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY;
|
||||
$options['@CipherOptions'] = $options['@CipherOptions'] ?? [];
|
||||
$options['@CipherOptions']['Iv'] = str_repeat("\1", 12);
|
||||
$options['@CipherOptions']['TagLength'] = $algorithmSuite->getCipherTagLengthInBytes();
|
||||
$materialDescription = json_decode(
|
||||
$envelope[MetadataEnvelope::ENCRYPTION_CONTEXT_V3],
|
||||
true
|
||||
);
|
||||
|
||||
|
||||
$cek = $provider->decryptCek(
|
||||
base64_decode($envelope[MetadataEnvelope::ENCRYPTED_DATA_KEY_V3]),
|
||||
$materialDescription,
|
||||
$options
|
||||
);
|
||||
|
||||
$options['@CipherOptions']['KeySize'] = strlen($cek) * 8;
|
||||
$options['@CipherOptions']['Cipher'] = $this->getCipherFromAesName(
|
||||
$this->numericalContenCipherToAesName($envelope)
|
||||
);
|
||||
$this->validateOptionsAndEnvelope($options, $envelope);
|
||||
|
||||
$messageId = base64_decode($envelope[MetadataEnvelope::MESSAGE_ID_V3]);
|
||||
$commitmentKey = base64_decode($envelope[MetadataEnvelope::KEY_COMMITMENT_V3]);
|
||||
|
||||
if (strlen($messageId) !== ($algorithmSuite->getKeyCommitmentSaltLengthBits()) / 8) {
|
||||
throw new CryptoException("Invalid MessageId length found in object envelope.");
|
||||
}
|
||||
|
||||
if (strlen($commitmentKey) !== $algorithmSuite->getCommitmentOutputKeyLengthBytes()) {
|
||||
throw new CryptoException("Invalid Commitment Key length found in object envelope.");
|
||||
}
|
||||
|
||||
$decryptionStream = $this->getCommitingDecryptingStream(
|
||||
$cipherText,
|
||||
$cek,
|
||||
$options['@CipherOptions'],
|
||||
$messageId,
|
||||
$commitmentKey,
|
||||
$algorithmSuite
|
||||
);
|
||||
unset($cek);
|
||||
|
||||
return $decryptionStream;
|
||||
} else {
|
||||
$options['@CipherOptions'] = $options['@CipherOptions'] ?? [];
|
||||
$options['@CipherOptions']['Iv'] = base64_decode(
|
||||
$envelope[MetadataEnvelope::IV_HEADER]
|
||||
);
|
||||
|
||||
$options['@CipherOptions']['TagLength'] =
|
||||
$envelope[MetadataEnvelope::CRYPTO_TAG_LENGTH_HEADER] / 8;
|
||||
|
||||
$cek = $provider->decryptCek(
|
||||
base64_decode(
|
||||
$envelope[MetadataEnvelope::CONTENT_KEY_V2_HEADER]
|
||||
),
|
||||
json_decode(
|
||||
$envelope[MetadataEnvelope::MATERIALS_DESCRIPTION_HEADER],
|
||||
true
|
||||
),
|
||||
$options
|
||||
);
|
||||
$options['@CipherOptions']['KeySize'] = strlen($cek) * 8;
|
||||
$options['@CipherOptions']['Cipher'] = $this->getCipherFromAesName(
|
||||
$envelope[MetadataEnvelope::CONTENT_CRYPTO_SCHEME_HEADER]
|
||||
);
|
||||
|
||||
$this->validateOptionsAndEnvelope($options, $envelope);
|
||||
|
||||
$decryptionStream = $this->getDecryptingStream(
|
||||
$cipherText,
|
||||
$cek,
|
||||
$options['@CipherOptions']
|
||||
);
|
||||
unset($cek);
|
||||
|
||||
return $decryptionStream;
|
||||
}
|
||||
}
|
||||
|
||||
private function buildMaterialDescription(
|
||||
MetadataEnvelope $envelope
|
||||
): array
|
||||
{
|
||||
switch ($envelope[MetadataEnvelope::ENCRYPTED_DATA_KEY_ALGORITHM_V3]) {
|
||||
case 12:
|
||||
return ['aws:x-amz-cek-alg' => '115'];
|
||||
default:
|
||||
throw new CryptoException(
|
||||
"Unknown Encrypted Data Key "
|
||||
. "wrapping algorithm found: "
|
||||
. "{$envelope[MetadataEnvelope::ENCRYPTED_DATA_KEY_ALGORITHM_V3]}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function numericalContenCipherToAesName(
|
||||
MetadataEnvelope $envelope
|
||||
): string
|
||||
{
|
||||
switch ($envelope[MetadataEnvelope::CONTENT_CIPHER_V3]) {
|
||||
case 115:
|
||||
return 'AES/GCM/NoPadding';
|
||||
default:
|
||||
throw new CryptoException(
|
||||
"Unknown Encrypted Data Key "
|
||||
. "wrapping algorithm found: "
|
||||
. "{$envelope[MetadataEnvelope::ENCRYPTED_DATA_KEY_ALGORITHM_V3]}"
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private function getTagFromCiphertextStream(
|
||||
StreamInterface $cipherText,
|
||||
$tagLength
|
||||
)
|
||||
{
|
||||
$cipherTextSize = $cipherText->getSize();
|
||||
if ($cipherTextSize == null || $cipherTextSize <= 0) {
|
||||
throw new \RuntimeException('Cannot decrypt a stream of unknown'
|
||||
. ' size.');
|
||||
}
|
||||
return (string) new LimitStream(
|
||||
$cipherText,
|
||||
$tagLength,
|
||||
$cipherTextSize - $tagLength
|
||||
);
|
||||
}
|
||||
|
||||
private function getStrippedCiphertextStream(
|
||||
StreamInterface $cipherText,
|
||||
$tagLength
|
||||
)
|
||||
{
|
||||
$cipherTextSize = $cipherText->getSize();
|
||||
if ($cipherTextSize == null || $cipherTextSize <= 0) {
|
||||
throw new \RuntimeException('Cannot decrypt a stream of unknown'
|
||||
. ' size.');
|
||||
}
|
||||
return new LimitStream(
|
||||
$cipherText,
|
||||
$cipherTextSize - $tagLength,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
private function validateOptionsAndEnvelope($options, $envelope): void
|
||||
{
|
||||
$allowedCiphers = AbstractCryptoClientV2::$supportedCiphers;
|
||||
$allowedKeywraps = AbstractCryptoClientV2::$supportedKeyWraps;
|
||||
if ($options['@SecurityProfile'] == 'V2_AND_LEGACY') {
|
||||
$allowedCiphers = array_unique(array_merge(
|
||||
$allowedCiphers,
|
||||
AbstractCryptoClient::$supportedCiphers
|
||||
));
|
||||
$allowedKeywraps = array_unique(array_merge(
|
||||
$allowedKeywraps,
|
||||
AbstractCryptoClient::$supportedKeyWraps
|
||||
));
|
||||
}
|
||||
|
||||
$v1SchemaException = new CryptoException("The requested object is encrypted"
|
||||
. " with V1 encryption schemas that have been disabled by"
|
||||
. " client configuration @SecurityProfile=V2. Retry with"
|
||||
. " V2_AND_LEGACY enabled or reencrypt the object.");
|
||||
|
||||
if (!in_array($options['@CipherOptions']['Cipher'], $allowedCiphers)) {
|
||||
if (in_array($options['@CipherOptions']['Cipher'], AbstractCryptoClient::$supportedCiphers)) {
|
||||
throw $v1SchemaException;
|
||||
}
|
||||
throw new CryptoException("The requested object is encrypted with"
|
||||
. " the cipher '{$options['@CipherOptions']['Cipher']}', which is not"
|
||||
. " supported for decryption with the selected security profile."
|
||||
. " This profile allows decryption with: "
|
||||
. implode(", ", $allowedCiphers));
|
||||
}
|
||||
|
||||
if (isset($envelope[MetadataEnvelope::ENCRYPTED_DATA_KEY_V3])) {
|
||||
if ($envelope[MetadataEnvelope::ENCRYPTED_DATA_KEY_ALGORITHM_V3] !== '12') {
|
||||
throw new CryptoException("The requested object is encrypted with"
|
||||
. " the keywrap schema '{$envelope[MetadataEnvelope::ENCRYPTED_DATA_KEY_ALGORITHM_V3]}',"
|
||||
. " which is not supported for decryption with the current security"
|
||||
. " profile.");
|
||||
}
|
||||
} else {
|
||||
if (!in_array($envelope[MetadataEnvelope::KEY_WRAP_ALGORITHM_HEADER], $allowedKeywraps)) {
|
||||
if (in_array($envelope[MetadataEnvelope::KEY_WRAP_ALGORITHM_HEADER], AbstractCryptoClient::$supportedKeyWraps)) {
|
||||
throw $v1SchemaException;
|
||||
}
|
||||
|
||||
throw new CryptoException("The requested object is encrypted with"
|
||||
. " the keywrap schema '{$envelope[MetadataEnvelope::KEY_WRAP_ALGORITHM_HEADER]}',"
|
||||
. " which is not supported for decryption with the current security"
|
||||
. " profile.");
|
||||
}
|
||||
$matdesc = json_decode(
|
||||
$envelope[MetadataEnvelope::MATERIALS_DESCRIPTION_HEADER],
|
||||
true
|
||||
);
|
||||
if (isset($matdesc['aws:x-amz-cek-alg'])
|
||||
&& ($envelope[MetadataEnvelope::CONTENT_CRYPTO_SCHEME_HEADER]
|
||||
!== $matdesc['aws:x-amz-cek-alg'])
|
||||
) {
|
||||
throw new CryptoException("There is a mismatch in specified content"
|
||||
. " encryption algrithm between the materials description value"
|
||||
. " and the metadata envelope value: {$matdesc['aws:x-amz-cek-alg']}"
|
||||
. " vs. {$envelope[MetadataEnvelope::CONTENT_CRYPTO_SCHEME_HEADER]}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a stream that wraps the cipher text with the proper cipher and
|
||||
* uses the content encryption key (CEK) to decrypt the data when read.
|
||||
*
|
||||
* @param string $cipherText 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
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
protected function getDecryptingStream(
|
||||
$cipherText,
|
||||
$cek,
|
||||
$cipherOptions
|
||||
)
|
||||
{
|
||||
$cipherTextStream = Psr7\Utils::streamFor($cipherText);
|
||||
switch ($cipherOptions['Cipher']) {
|
||||
case 'gcm':
|
||||
$cipherOptions['Tag'] = $this->getTagFromCiphertextStream(
|
||||
$cipherTextStream,
|
||||
$cipherOptions['TagLength']
|
||||
);
|
||||
|
||||
return new AesGcmDecryptingStream(
|
||||
$this->getStrippedCiphertextStream(
|
||||
$cipherTextStream,
|
||||
$cipherOptions['TagLength']
|
||||
),
|
||||
$cek,
|
||||
$cipherOptions['Iv'],
|
||||
$cipherOptions['Tag'],
|
||||
$cipherOptions['Aad'] = $cipherOptions['Aad'] ?? '',
|
||||
$cipherOptions['TagLength'] ?: null,
|
||||
$cipherOptions['KeySize']
|
||||
);
|
||||
default:
|
||||
$cipherMethod = $this->buildCipherMethod(
|
||||
$cipherOptions['Cipher'],
|
||||
$cipherOptions['Iv'],
|
||||
$cipherOptions['KeySize']
|
||||
);
|
||||
return new AesDecryptingStream(
|
||||
$cipherTextStream,
|
||||
$cek,
|
||||
$cipherMethod
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a stream that wraps the cipher text with the proper cipher and
|
||||
* uses the content encryption key (CEK) to derive both a derived content encryption key
|
||||
* and a commitment key to decrypt the data when read.
|
||||
*
|
||||
* @param string $cipherText 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.
|
||||
* @param string $messageId a string value used to calculate both a commitment
|
||||
* key and derived content encryption key
|
||||
* @param string $commitmentKey a string value to compare with the calculated commitment
|
||||
* key value, if the values don't match an exception is raised.
|
||||
*
|
||||
* @return AesStreamInterface | CryptoException
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
protected function getCommitingDecryptingStream(
|
||||
string $cipherText,
|
||||
string $cek,
|
||||
array $cipherOptions,
|
||||
string $messageId,
|
||||
string $commitmentKey,
|
||||
AlgorithmSuite $algorithmSuite
|
||||
): AesStreamInterface|CryptoException
|
||||
{
|
||||
$algorithmSuiteIdAsBytes = pack('n', $algorithmSuite->getId());
|
||||
$derivedEncryptionKeyInfo = $algorithmSuiteIdAsBytes . "DERIVEKEY";
|
||||
$commitmentKeyInfo = $algorithmSuiteIdAsBytes . "COMMITKEY";
|
||||
$derivedEncryptionKey = hash_hkdf(
|
||||
$algorithmSuite->getHashingAlgorithm(),
|
||||
$cek,
|
||||
$algorithmSuite->getDerivationOutputKeyLengthBytes(),
|
||||
$derivedEncryptionKeyInfo,
|
||||
$messageId
|
||||
);
|
||||
$calculatedCommitmentKey = hash_hkdf(
|
||||
$algorithmSuite->getHashingAlgorithm(),
|
||||
$cek,
|
||||
$algorithmSuite->getCommitmentOutputKeyLengthBytes(),
|
||||
$commitmentKeyInfo,
|
||||
$messageId
|
||||
);
|
||||
|
||||
if ($commitmentKey != $calculatedCommitmentKey) {
|
||||
throw new CryptoException("Calculated commitment key does "
|
||||
. "not match expected commitment key value ");
|
||||
}
|
||||
|
||||
$cipherTextStream = Psr7\Utils::streamFor($cipherText);
|
||||
switch ($cipherOptions['Cipher']) {
|
||||
case 'gcm':
|
||||
$cipherOptions['Tag'] = $this->getTagFromCiphertextStream(
|
||||
$cipherTextStream,
|
||||
$cipherOptions['TagLength']
|
||||
);
|
||||
$cipherOptions['Aad'] = isset($cipherOptions['Aad'])
|
||||
? $cipherOptions['Aad'] + $algorithmSuiteIdAsBytes
|
||||
: $algorithmSuiteIdAsBytes;
|
||||
|
||||
return new AesGcmDecryptingStream(
|
||||
$this->getStrippedCiphertextStream(
|
||||
$cipherTextStream,
|
||||
$cipherOptions['TagLength']
|
||||
),
|
||||
$derivedEncryptionKey,
|
||||
$cipherOptions['Iv'],
|
||||
$cipherOptions['Tag'],
|
||||
$cipherOptions['Aad'],
|
||||
$cipherOptions['TagLength'] ?: null,
|
||||
$cipherOptions['KeySize']
|
||||
);
|
||||
default:
|
||||
throw new CryptoException("Unsupported Cipher used for key commitment messages."
|
||||
. " Found {$cipherOptions["Cipher"]}. Only 'gcm' is supported.");
|
||||
}
|
||||
}
|
||||
}
|
||||
530
vendor/aws/aws-sdk-php/src/Crypto/DecryptionTraitV3.php
vendored
Normal file
530
vendor/aws/aws-sdk-php/src/Crypto/DecryptionTraitV3.php
vendored
Normal file
@@ -0,0 +1,530 @@
|
||||
<?php
|
||||
|
||||
namespace Aws\Crypto;
|
||||
|
||||
use Aws\Crypto\Cipher\CipherMethod;
|
||||
use Aws\Exception\CryptoException;
|
||||
use GuzzleHttp\Psr7;
|
||||
use GuzzleHttp\Psr7\LimitStream;
|
||||
use PHPUnit\Framework\Constraint\IsEmpty;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
trait DecryptionTraitV3
|
||||
{
|
||||
/**
|
||||
* Dependency to reverse lookup the openssl_* cipher name from the AESName
|
||||
* in the MetadataEnvelope.
|
||||
*
|
||||
* @param string $aesName
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
abstract protected function getCipherFromAesName($aesName);
|
||||
|
||||
/**
|
||||
* Dependency to generate a CipherMethod from a set of inputs for loading
|
||||
* in to an AesDecryptingStream.
|
||||
*
|
||||
* @param string $cipherName Name of the cipher to generate for decrypting.
|
||||
* @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 using cipher options loaded from the
|
||||
* MetadataEnvelope and MaterialsProvider. Can decrypt data from both the
|
||||
* legacy and V3 encryption client workflows.
|
||||
*
|
||||
* @param string $cipherText Plain-text data to be encrypted using the
|
||||
* materials, algorithm, and data provided.
|
||||
* @param MaterialsProviderInterfaceV3 $provider A provider to supply and encrypt
|
||||
* materials used in encryption.
|
||||
* @param MetadataEnvelope $envelope A storage envelope for encryption
|
||||
* metadata to be read from.
|
||||
* @param string $commitmentPolicy Commitment Policy to use for decrypting objects.
|
||||
* @param array $options Options used for decryption.
|
||||
*
|
||||
* @return AesStreamInterface
|
||||
*
|
||||
* @throws \InvalidArgumentException Thrown when a value in $cipherOptions
|
||||
* is not valid.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function decrypt(
|
||||
string $cipherText,
|
||||
MaterialsProviderInterfaceV3 $provider,
|
||||
MetadataEnvelope $envelope,
|
||||
string $commitmentPolicy,
|
||||
array $options = []
|
||||
): AesStreamInterface
|
||||
{
|
||||
if (isset($envelope[MetadataEnvelope::ENCRYPTED_DATA_KEY_V3])) {
|
||||
$this->checkEnvelopeForExclusiveMapKeys(
|
||||
$envelope,
|
||||
MetadataEnvelope::getV2Fields(),
|
||||
"Expected V3 only fields but found V2 fields in header metadata."
|
||||
);
|
||||
// PHP only supports one commiting algorithm suite
|
||||
$algorithmSuite = AlgorithmSuite::ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY;
|
||||
$options['@CipherOptions'] = $options['@CipherOptions'] ?? [];
|
||||
$options['@CipherOptions']['Iv'] = str_repeat("\1", 12);
|
||||
$options['@CipherOptions']['TagLength'] = $algorithmSuite->getCipherTagLengthInBytes();
|
||||
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#v3-only
|
||||
//= type=implication
|
||||
//# - The wrapping algorithm value "12" MUST be translated to kms+context upon retrieval, and vice versa on write.
|
||||
$materialDescription = $this->buildMaterialDescription($envelope);
|
||||
|
||||
$cek = $provider->decryptCek(
|
||||
base64_decode($envelope[MetadataEnvelope::ENCRYPTED_DATA_KEY_V3]),
|
||||
$materialDescription,
|
||||
$options
|
||||
);
|
||||
|
||||
$options['@CipherOptions']['KeySize'] = strlen($cek) * 8;
|
||||
$options['@CipherOptions']['Cipher'] = $this->getCipherFromAesName(
|
||||
$this->numericalContenCipherToAesName($envelope)
|
||||
);
|
||||
$this->validateOptionsAndEnvelope($options, $envelope, $commitmentPolicy);
|
||||
|
||||
$messageId = base64_decode($envelope[MetadataEnvelope::MESSAGE_ID_V3]);
|
||||
$commitmentKey = base64_decode($envelope[MetadataEnvelope::KEY_COMMITMENT_V3]);
|
||||
|
||||
if (strlen($messageId) !== ($algorithmSuite->getKeyCommitmentSaltLengthBits()) / 8) {
|
||||
throw new CryptoException("Invalid MessageId length found in object envelope.");
|
||||
}
|
||||
|
||||
if (strlen($commitmentKey) !== $algorithmSuite->getCommitmentOutputKeyLengthBytes()) {
|
||||
throw new CryptoException("Invalid Commitment Key length found in object envelope.");
|
||||
}
|
||||
|
||||
$decryptionStream = $this->getCommitingDecryptingStream(
|
||||
$cipherText,
|
||||
$cek,
|
||||
$options['@CipherOptions'],
|
||||
$messageId,
|
||||
$commitmentKey,
|
||||
$algorithmSuite
|
||||
);
|
||||
unset($cek);
|
||||
|
||||
return $decryptionStream;
|
||||
} else {
|
||||
//= ../specification/s3-encryption/key-commitment.md#commitment-policy
|
||||
//# When the commitment policy is REQUIRE_ENCRYPT_REQUIRE_DECRYPT,
|
||||
//# the S3EC MUST NOT allow decryption using algorithm suites which do not support key commitment.
|
||||
if ($commitmentPolicy == "REQUIRE_ENCRYPT_REQUIRE_DECRYPT") {
|
||||
//= ../specification/s3-encryption/client.md#key-commitment
|
||||
//# If the configured Encryption Algorithm is incompatible with
|
||||
//# the key commitment policy, then it MUST throw an exception.
|
||||
throw new CryptoException("Message is encrypted with a "
|
||||
. "non commiting algorithm but commitment policy is set "
|
||||
. "to {$commitmentPolicy}. Select a valid commitment "
|
||||
. "policy to decrypt this object. ");
|
||||
}
|
||||
$this->checkEnvelopeForExclusiveMapKeys(
|
||||
$envelope,
|
||||
MetadataEnvelope::getV3Fields(),
|
||||
"Expected V2 only fields but found V3 fields in header metadata."
|
||||
);
|
||||
$options['@CipherOptions'] = $options['@CipherOptions'] ?? [];
|
||||
$options['@CipherOptions']['Iv'] = base64_decode(
|
||||
$envelope[MetadataEnvelope::IV_HEADER]
|
||||
);
|
||||
|
||||
$options['@CipherOptions']['TagLength'] =
|
||||
$envelope[MetadataEnvelope::CRYPTO_TAG_LENGTH_HEADER] / 8;
|
||||
|
||||
$cek = $provider->decryptCek(
|
||||
base64_decode(
|
||||
$envelope[MetadataEnvelope::CONTENT_KEY_V2_HEADER]
|
||||
),
|
||||
json_decode(
|
||||
$envelope[MetadataEnvelope::MATERIALS_DESCRIPTION_HEADER],
|
||||
true
|
||||
),
|
||||
$options
|
||||
);
|
||||
$options['@CipherOptions']['KeySize'] = strlen($cek) * 8;
|
||||
$options['@CipherOptions']['Cipher'] = $this->getCipherFromAesName(
|
||||
$envelope[MetadataEnvelope::CONTENT_CRYPTO_SCHEME_HEADER]
|
||||
);
|
||||
|
||||
//= ../specification/s3-encryption/decryption.md#key-commitment
|
||||
//= type=implication
|
||||
//# The S3EC MUST validate the algorithm suite used for decryption
|
||||
//# against the key commitment policy before attempting to decrypt
|
||||
//# the content ciphertext.
|
||||
$this->validateOptionsAndEnvelope($options, $envelope, $commitmentPolicy);
|
||||
|
||||
$decryptionStream = $this->getNonCommitingDecryptingStream(
|
||||
$cipherText,
|
||||
$cek,
|
||||
$options['@CipherOptions']
|
||||
);
|
||||
unset($cek);
|
||||
|
||||
return $decryptionStream;
|
||||
}
|
||||
}
|
||||
|
||||
private function checkEnvelopeForExclusiveMapKeys(
|
||||
MetadataEnvelope $envelope,
|
||||
array $exclusiveKeys,
|
||||
string $errorMessage
|
||||
): void
|
||||
{
|
||||
foreach ($exclusiveKeys as $exclusiveKey) {
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#determining-s3ec-object-status
|
||||
//# If there are multiple mapkeys which are meant to be exclusive, such as "x-amz-key", "x-amz-key-v2", and "x-amz-3" then the S3EC SHOULD throw an exception.
|
||||
if (isset($envelope[$exclusiveKey])) {
|
||||
throw new CryptoException($errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function numericalContenCipherToAesName(
|
||||
MetadataEnvelope $envelope
|
||||
): string
|
||||
{
|
||||
switch ($envelope[MetadataEnvelope::CONTENT_CIPHER_V3]) {
|
||||
case 115:
|
||||
return 'AES/GCM/NoPadding';
|
||||
default:
|
||||
throw new CryptoException(
|
||||
"Unknown Encrypted Data Key "
|
||||
. "wrapping algorithm found: "
|
||||
. "{$envelope[MetadataEnvelope::ENCRYPTED_DATA_KEY_ALGORITHM_V3]}"
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private function buildMaterialDescription(
|
||||
MetadataEnvelope $envelope
|
||||
): array
|
||||
{
|
||||
switch ($envelope[MetadataEnvelope::ENCRYPTED_DATA_KEY_ALGORITHM_V3]) {
|
||||
case 12:
|
||||
return json_decode(
|
||||
$envelope[MetadataEnvelope::ENCRYPTION_CONTEXT_V3],
|
||||
true
|
||||
);
|
||||
default:
|
||||
throw new CryptoException(
|
||||
"Unknown Encrypted Data Key "
|
||||
. "wrapping algorithm found: "
|
||||
. "{$envelope[MetadataEnvelope::ENCRYPTED_DATA_KEY_ALGORITHM_V3]}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function getTagFromCiphertextStream(
|
||||
StreamInterface $cipherText,
|
||||
$tagLength
|
||||
): string
|
||||
{
|
||||
$cipherTextSize = $cipherText->getSize();
|
||||
if ($cipherTextSize == null || $cipherTextSize <= 0) {
|
||||
throw new \RuntimeException('Cannot decrypt a stream of unknown size');
|
||||
}
|
||||
|
||||
return (string) new LimitStream(
|
||||
$cipherText,
|
||||
$tagLength,
|
||||
$cipherTextSize - $tagLength
|
||||
);
|
||||
}
|
||||
|
||||
private function getStrippedCiphertextStream(
|
||||
StreamInterface $cipherText,
|
||||
$tagLength
|
||||
): LimitStream
|
||||
{
|
||||
$cipherTextSize = $cipherText->getSize();
|
||||
if ($cipherTextSize == null || $cipherTextSize <= 0) {
|
||||
throw new \RuntimeException('Cannot decrypt a stream of unknown size');
|
||||
}
|
||||
|
||||
return new LimitStream(
|
||||
$cipherText,
|
||||
$cipherTextSize - $tagLength,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
private function validateOptionsAndEnvelope(
|
||||
array $options,
|
||||
MetadataEnvelope $envelope,
|
||||
string $commitmentPolicy
|
||||
): void
|
||||
{
|
||||
//= ../specification/s3-encryption/key-commitment.md#commitment-policy
|
||||
//# When the commitment policy is REQUIRE_ENCRYPT_ALLOW_DECRYPT,
|
||||
//# the S3EC MUST allow decryption using algorithm suites which do not support key commitment.
|
||||
|
||||
//= ../specification/s3-encryption/key-commitment.md#commitment-policy
|
||||
//# When the commitment policy is FORBID_ENCRYPT_ALLOW_DECRYPT,
|
||||
//# the S3EC MUST allow decryption using algorithm suites which do not support key commitment.
|
||||
|
||||
$allowedCiphers = AbstractCryptoClientV3::$supportedCiphers;
|
||||
$allowedKeywraps = AbstractCryptoClientV3::$supportedKeyWraps;
|
||||
//= ../specification/s3-encryption/client.md#enable-legacy-wrapping-algorithms
|
||||
//# When enabled, the S3EC MUST be able to decrypt objects encrypted with all
|
||||
//# supported wrapping algorithms (both legacy and fully supported).
|
||||
if ($options['@SecurityProfile'] == 'V3_AND_LEGACY') {
|
||||
$allowedCiphers = array_unique(array_merge(
|
||||
$allowedCiphers,
|
||||
AbstractCryptoClient::$supportedCiphers
|
||||
));
|
||||
$allowedKeywraps = array_unique(array_merge(
|
||||
$allowedKeywraps,
|
||||
AbstractCryptoClient::$supportedKeyWraps
|
||||
));
|
||||
}
|
||||
|
||||
$v1SchemaException = new CryptoException("The requested object is encrypted"
|
||||
. " with V1 encryption schemas that have been disabled by"
|
||||
. " client configuration @SecurityProfile=V3. Retry with"
|
||||
. " V3_AND_LEGACY enabled or reencrypt the object.");
|
||||
|
||||
if (!in_array($options['@CipherOptions']['Cipher'], $allowedCiphers)) {
|
||||
//= ../specification/s3-encryption/client.md#enable-legacy-wrapping-algorithms
|
||||
//= type=implication
|
||||
//# When disabled, the S3EC MUST NOT decrypt objects encrypted using legacy wrapping algorithms;
|
||||
//# it MUST throw an exception when attempting to decrypt an object encrypted with a legacy wrapping algorithm.
|
||||
|
||||
//= ../specification/s3-encryption/decryption.md#legacy-decryption
|
||||
//# The S3EC MUST NOT decrypt objects encrypted using legacy unauthenticated algorithm suites unless specifically configured to do so.
|
||||
if (in_array($options['@CipherOptions']['Cipher'], AbstractCryptoClient::$supportedCiphers)) {
|
||||
//= ../specification/s3-encryption/decryption.md#legacy-decryption
|
||||
//# If the S3EC is not configured to enable legacy unauthenticated content decryption, the client MUST throw an exception when attempting to decrypt an object encrypted with a legacy unauthenticated algorithm suite.
|
||||
throw $v1SchemaException;
|
||||
}
|
||||
|
||||
throw new CryptoException("The requested object is encrypted with"
|
||||
. " the cipher '{$options['@CipherOptions']['Cipher']}', which is not"
|
||||
. " supported for decryption with the selected security profile."
|
||||
. " This profile allows decryption with: "
|
||||
. implode(", ", $allowedCiphers));
|
||||
}
|
||||
|
||||
if (isset($envelope[MetadataEnvelope::ENCRYPTED_DATA_KEY_V3])) {
|
||||
if ($envelope[MetadataEnvelope::ENCRYPTED_DATA_KEY_ALGORITHM_V3] !== '12') {
|
||||
throw new CryptoException("The requested object is encrypted with"
|
||||
. " the keywrap schema '{$envelope[MetadataEnvelope::ENCRYPTED_DATA_KEY_ALGORITHM_V3]}',"
|
||||
. " which is not supported for decryption with the current security"
|
||||
. " profile.");
|
||||
}
|
||||
} else {
|
||||
if (!in_array($envelope[MetadataEnvelope::KEY_WRAP_ALGORITHM_HEADER], $allowedKeywraps)) {
|
||||
if (in_array($envelope[MetadataEnvelope::KEY_WRAP_ALGORITHM_HEADER], AbstractCryptoClient::$supportedKeyWraps)) {
|
||||
throw $v1SchemaException;
|
||||
}
|
||||
|
||||
throw new CryptoException("The requested object is encrypted with"
|
||||
. " the keywrap schema '{$envelope[MetadataEnvelope::KEY_WRAP_ALGORITHM_HEADER]}',"
|
||||
. " which is not supported for decryption with the current security"
|
||||
. " profile.");
|
||||
}
|
||||
$matdesc = json_decode(
|
||||
$envelope[MetadataEnvelope::MATERIALS_DESCRIPTION_HEADER],
|
||||
true
|
||||
);
|
||||
if (isset($matdesc['aws:x-amz-cek-alg'])
|
||||
&& ($envelope[MetadataEnvelope::CONTENT_CRYPTO_SCHEME_HEADER]
|
||||
!== $matdesc['aws:x-amz-cek-alg'])
|
||||
) {
|
||||
throw new CryptoException("There is a mismatch in specified content"
|
||||
. " encryption algrithm between the materials description value"
|
||||
. " and the metadata envelope value: {$matdesc['aws:x-amz-cek-alg']}"
|
||||
. " vs. {$envelope[MetadataEnvelope::CONTENT_CRYPTO_SCHEME_HEADER]}.");
|
||||
}
|
||||
}
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#determining-s3ec-object-status
|
||||
//= type=implication
|
||||
//# - If the metadata contains "x-amz-3" and "x-amz-d" and "x-amz-i" then the object MUST be considered an S3EC-encrypted object using the V3 format.
|
||||
if (!MetadataEnvelope::isV3Envelope($envelope)
|
||||
&& $commitmentPolicy == "REQUIRE_ENCRYPT_REQUIRE_DECRYPT"
|
||||
) {
|
||||
//= ../specification/s3-encryption/decryption.md#key-commitment
|
||||
//# If the commitment policy requires decryption using a committing algorithm suite
|
||||
//# and the algorithm suite associated with the object does not support key commitment,
|
||||
//# then the S3EC MUST throw an exception.
|
||||
throw new CryptoException("There is a mismatch in specified"
|
||||
. "commitment policy value {$commitmentPolicy} and"
|
||||
. "Metadata Envelope found in object.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a stream that wraps the cipher text with the proper cipher and
|
||||
* uses the content encryption key (CEK) to decrypt the data when read.
|
||||
*
|
||||
* @param string $cipherText 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
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
protected function getNonCommitingDecryptingStream(
|
||||
string $cipherText,
|
||||
string $cek,
|
||||
array $cipherOptions
|
||||
): AesStreamInterface
|
||||
{
|
||||
$cipherTextStream = Psr7\Utils::streamFor($cipherText);
|
||||
switch ($cipherOptions['Cipher']) {
|
||||
case 'gcm':
|
||||
$cipherOptions['Tag'] = $this->getTagFromCiphertextStream(
|
||||
$cipherTextStream,
|
||||
$cipherOptions['TagLength']
|
||||
);
|
||||
|
||||
return new AesGcmDecryptingStream(
|
||||
$this->getStrippedCiphertextStream(
|
||||
$cipherTextStream,
|
||||
$cipherOptions['TagLength']
|
||||
),
|
||||
$cek,
|
||||
$cipherOptions['Iv'],
|
||||
$cipherOptions['Tag'],
|
||||
$cipherOptions['Aad'] = isset($cipherOptions['Aad'])
|
||||
? $cipherOptions['Aad']
|
||||
: '',
|
||||
$cipherOptions['TagLength'] ?: null,
|
||||
$cipherOptions['KeySize']
|
||||
);
|
||||
default:
|
||||
$cipherMethod = $this->buildCipherMethod(
|
||||
$cipherOptions['Cipher'],
|
||||
$cipherOptions['Iv'],
|
||||
$cipherOptions['KeySize']
|
||||
);
|
||||
|
||||
return new AesDecryptingStream(
|
||||
$cipherTextStream,
|
||||
$cek,
|
||||
$cipherMethod
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a stream that wraps the cipher text with the proper cipher and
|
||||
* uses the content encryption key (CEK) to derive both a derived content encryption key
|
||||
* and a commitment key to decrypt the data when read.
|
||||
*
|
||||
* @param string $cipherText 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.
|
||||
* @param string $messageId a string value used to calculate both a commitment
|
||||
* key and derived content encryption key
|
||||
* @param string $commitmentKey a string value to compare with the calculated commitment
|
||||
* key value, if the values don't match an exception is raised.
|
||||
*
|
||||
* @return AesStreamInterface | CryptoException
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
protected function getCommitingDecryptingStream(
|
||||
string $cipherText,
|
||||
string $cek,
|
||||
array $cipherOptions,
|
||||
string $messageId,
|
||||
string $commitmentKey,
|
||||
AlgorithmSuite $algorithmSuite
|
||||
): AesStreamInterface|CryptoException
|
||||
{
|
||||
$algorithmSuiteIdAsBytes = pack('n', $algorithmSuite->getId());
|
||||
$derivedEncryptionKeyInfo = $algorithmSuiteIdAsBytes . "DERIVEKEY";
|
||||
$commitmentKeyInfo = $algorithmSuiteIdAsBytes . "COMMITKEY";
|
||||
$calculatedCommitmentKey = hash_hkdf(
|
||||
$algorithmSuite->getHashingAlgorithm(),
|
||||
$cek,
|
||||
$algorithmSuite->getCommitmentOutputKeyLengthBytes(),
|
||||
$commitmentKeyInfo,
|
||||
$messageId
|
||||
);
|
||||
//= ../specification/s3-encryption/decryption.md#decrypting-with-commitment
|
||||
//= type=implication
|
||||
//# When using an algorithm suite which supports key commitment, the client MUST verify that the [derived key commitment](./key-derivation.md#hkdf-operation) contains the same bytes as the stored key commitment retrieved from the stored object's metadata.
|
||||
if (
|
||||
//= ../specification/s3-encryption/decryption.md#decrypting-with-commitment
|
||||
//= type=implication
|
||||
//# When using an algorithm suite which supports key commitment,
|
||||
//# the verification of the derived key commitment value MUST be done in constant time.
|
||||
!hash_equals($commitmentKey, $calculatedCommitmentKey)
|
||||
) {
|
||||
//= ../specification/s3-encryption/decryption.md#decrypting-with-commitment
|
||||
//= type=implication
|
||||
//# When using an algorithm suite which supports key commitment, the client MUST
|
||||
//# throw an exception when the derived key commitment value
|
||||
//# and stored key commitment value do not match.
|
||||
throw new CryptoException("Calculated commitment key does "
|
||||
. "not match expected commitment key value ");
|
||||
}
|
||||
//= ../specification/s3-encryption/decryption.md#decrypting-with-commitment
|
||||
//= type=implication
|
||||
//# When using an algorithm suite which supports key commitment,
|
||||
//# the client MUST verify the key commitment values match before
|
||||
//# deriving the [derived encryption key](./key-derivation.md#hkdf-operation).
|
||||
$derivedEncryptionKey = hash_hkdf(
|
||||
$algorithmSuite->getHashingAlgorithm(),
|
||||
$cek,
|
||||
$algorithmSuite->getDerivationOutputKeyLengthBytes(),
|
||||
$derivedEncryptionKeyInfo,
|
||||
$messageId
|
||||
);
|
||||
|
||||
$cipherTextStream = Psr7\Utils::streamFor($cipherText);
|
||||
switch ($cipherOptions['Cipher']) {
|
||||
case 'gcm':
|
||||
$cipherOptions['Tag'] = $this->getTagFromCiphertextStream(
|
||||
$cipherTextStream,
|
||||
$cipherOptions['TagLength']
|
||||
);
|
||||
$cipherOptions['Aad'] = isset($cipherOptions['Aad'])
|
||||
? $cipherOptions['Aad'] + $algorithmSuiteIdAsBytes
|
||||
: $algorithmSuiteIdAsBytes;
|
||||
|
||||
return new AesGcmDecryptingStream(
|
||||
$this->getStrippedCiphertextStream(
|
||||
$cipherTextStream,
|
||||
$cipherOptions['TagLength']
|
||||
),
|
||||
$derivedEncryptionKey,
|
||||
$cipherOptions['Iv'],
|
||||
$cipherOptions['Tag'],
|
||||
$cipherOptions['Aad'],
|
||||
$cipherOptions['TagLength'] ?: null,
|
||||
$cipherOptions['KeySize']
|
||||
);
|
||||
default:
|
||||
throw new CryptoException("Unsupported Cipher used for key commitment messages."
|
||||
. " Found {$cipherOptions["Cipher"]}. Only 'gcm' is supported.");
|
||||
}
|
||||
}
|
||||
}
|
||||
192
vendor/aws/aws-sdk-php/src/Crypto/EncryptionTrait.php
vendored
Normal file
192
vendor/aws/aws-sdk-php/src/Crypto/EncryptionTrait.php
vendored
Normal file
@@ -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 array returns an array with two elements as follows: [string, AesStreamInterface]
|
||||
*
|
||||
* @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']
|
||||
: '',
|
||||
$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()];
|
||||
}
|
||||
}
|
||||
}
|
||||
192
vendor/aws/aws-sdk-php/src/Crypto/EncryptionTraitV2.php
vendored
Normal file
192
vendor/aws/aws-sdk-php/src/Crypto/EncryptionTraitV2.php
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
<?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] =
|
||||
(string) strlen($plaintext);
|
||||
$envelope[MetadataEnvelope::MATERIALS_DESCRIPTION_HEADER] =
|
||||
json_encode($materialsDescription);
|
||||
if (!empty($cipherOptions['Tag'])) {
|
||||
$envelope[MetadataEnvelope::CRYPTO_TAG_LENGTH_HEADER] =
|
||||
(string) (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'] = $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;
|
||||
}
|
||||
}
|
||||
}
|
||||
474
vendor/aws/aws-sdk-php/src/Crypto/EncryptionTraitV3.php
vendored
Normal file
474
vendor/aws/aws-sdk-php/src/Crypto/EncryptionTraitV3.php
vendored
Normal file
@@ -0,0 +1,474 @@
|
||||
<?php
|
||||
namespace Aws\Crypto;
|
||||
|
||||
use Aws\Crypto\Cipher\CipherMethod;
|
||||
use Aws\Exception\CryptoException;
|
||||
use GuzzleHttp\Psr7;
|
||||
use GuzzleHttp\Psr7\AppendStream;
|
||||
use GuzzleHttp\Psr7\Stream;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
trait EncryptionTraitV3
|
||||
{
|
||||
private static array $allowedOptions = [
|
||||
'Cipher' => true,
|
||||
'KeySize' => true,
|
||||
'Aad' => true,
|
||||
];
|
||||
|
||||
private static array $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 AlgorithmSuite $algorithmSuite Algorithm Suite for use in encryption
|
||||
* @param array $options Options for use in encryption, including cipher
|
||||
* options, and encryption context.
|
||||
* @param MaterialsProviderV3 $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 AppendStream
|
||||
*
|
||||
* @throws \InvalidArgumentException Thrown when a value in $options['@CipherOptions']
|
||||
* is not valid.
|
||||
*s
|
||||
* @internal
|
||||
*/
|
||||
public function encrypt(
|
||||
Stream $plaintext,
|
||||
AlgorithmSuite $algorithmSuite,
|
||||
array $options,
|
||||
MaterialsProviderV3 $provider,
|
||||
MetadataEnvelope $envelope
|
||||
): AppendStream
|
||||
{
|
||||
$options = array_change_key_case($options);
|
||||
$cipherOptions = array_intersect_key(
|
||||
$options['@cipheroptions'],
|
||||
self::$allowedOptions
|
||||
);
|
||||
//= ../specification/s3-encryption/encryption.md#content-encryption
|
||||
//= type=implication
|
||||
//# The client MUST validate that the length of the plaintext bytes does not exceed
|
||||
//# the algorithm suite's cipher's maximum content length in bytes.
|
||||
if (strlen($plaintext) > $algorithmSuite->getCipherMaxContentLengthBytes()) {
|
||||
throw new \InvalidArgumentException("The contentLength of the object you are attempting"
|
||||
. " to encrypt exceeds the maximum length allowed for GCM encryption.");
|
||||
}
|
||||
$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 (!MaterialsProviderV3::isSupportedKeySize($cipherOptions['KeySize'])) {
|
||||
throw new \InvalidArgumentException('The cipher "KeySize" requested'
|
||||
. ' is not supported by AES (256).');
|
||||
}
|
||||
|
||||
$encryptClass = self::$encryptClasses[$algorithmSuite->getCipherName()];
|
||||
$aesName = $encryptClass::getStaticAesName();
|
||||
$materialsDescription = $algorithmSuite->isKeyCommitting()
|
||||
? ['aws:x-amz-cek-alg' => '115']
|
||||
: ['aws:x-amz-cek-alg' => $aesName];
|
||||
|
||||
$keys = $provider->generateCek(
|
||||
$algorithmSuite->getDataKeyLengthBits(),
|
||||
$materialsDescription,
|
||||
$options
|
||||
);
|
||||
|
||||
// Some providers modify materials description based on options
|
||||
if (isset($keys['UpdatedContext'])) {
|
||||
$materialsDescription = $keys['UpdatedContext'];
|
||||
}
|
||||
|
||||
if ($algorithmSuite->isKeyCommitting()) {
|
||||
return $this->encryptCommitingStream(
|
||||
$plaintext,
|
||||
$algorithmSuite,
|
||||
$cipherOptions,
|
||||
$keys,
|
||||
$materialsDescription,
|
||||
$provider,
|
||||
$envelope
|
||||
);
|
||||
} else {
|
||||
return $this->encryptNonCommitingStream(
|
||||
$plaintext,
|
||||
$cipherOptions,
|
||||
$keys,
|
||||
$materialsDescription,
|
||||
$aesName,
|
||||
$provider,
|
||||
$envelope
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function encryptNonCommitingStream(
|
||||
Stream $plaintext,
|
||||
array &$cipherOptions,
|
||||
array $keys,
|
||||
array $materialsDescription,
|
||||
string $aesName,
|
||||
MaterialsProviderV3 $provider,
|
||||
MetadataEnvelope $envelope
|
||||
): AppendStream
|
||||
{
|
||||
//= ../specification/s3-encryption/encryption.md#content-encryption
|
||||
//# The generated IV or Message ID MUST be set or returned from the
|
||||
//# encryption process such that it can be included in the content metadata.
|
||||
//= ../specification/s3-encryption/encryption.md#content-encryption
|
||||
//# The client MUST generate an IV or Message ID using the length of the IV or Message ID defined in the algorithm suite.
|
||||
$cipherOptions['Iv'] = $provider->generateIv(
|
||||
$this->getCipherOpenSslName(
|
||||
$cipherOptions['Cipher'],
|
||||
$cipherOptions['KeySize']
|
||||
)
|
||||
);
|
||||
// Some providers modify materials description based on options
|
||||
if (isset($keys['UpdatedContext'])) {
|
||||
$materialsDescription = $keys['UpdatedContext'];
|
||||
}
|
||||
|
||||
$encryptingStream = $this->getNonCommittingEncryptingStream(
|
||||
$plaintext,
|
||||
$keys['Plaintext'],
|
||||
$cipherOptions
|
||||
);
|
||||
|
||||
// Populate envelope data
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#determining-s3ec-object-status
|
||||
//# - If the metadata contains "x-amz-iv" and "x-amz-metadata-x-amz-key-v2" then the object MUST be considered as an S3EC-encrypted object using the V2 format.
|
||||
$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] =
|
||||
(string) strlen($plaintext);
|
||||
$envelope[MetadataEnvelope::MATERIALS_DESCRIPTION_HEADER] =
|
||||
json_encode($materialsDescription);
|
||||
if (!empty($cipherOptions['Tag'])) {
|
||||
$envelope[MetadataEnvelope::CRYPTO_TAG_LENGTH_HEADER] =
|
||||
(string) (strlen($cipherOptions['Tag']) * 8);
|
||||
}
|
||||
if (!MetadataEnvelope::isV2Envelope($envelope)) {
|
||||
throw new CryptoException("Error while writing metadata envelope."
|
||||
. " Not all required fields were set.");
|
||||
}
|
||||
|
||||
return $encryptingStream;
|
||||
}
|
||||
|
||||
private function encryptCommitingStream(
|
||||
Stream $plaintext,
|
||||
AlgorithmSuite $algorithmSuite,
|
||||
array &$options,
|
||||
array $keys,
|
||||
array $materialsDescription,
|
||||
MaterialsProviderV3 $provider,
|
||||
MetadataEnvelope $envelope
|
||||
): AppendStream
|
||||
{
|
||||
//= ../specification/s3-encryption/encryption.md#content-encryption
|
||||
//# The generated IV or Message ID MUST be set or returned from the
|
||||
//# encryption process such that it can be included in the content metadata.
|
||||
//= ../specification/s3-encryption/key-derivation.md#hkdf-operation
|
||||
//= type=implication
|
||||
//# When encrypting or decrypting with ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY,
|
||||
//# the IV used in the AES-GCM content encryption/decryption
|
||||
//# MUST consist entirely of bytes with the value 0x01.
|
||||
//= ../specification/s3-encryption/key-derivation.md#hkdf-operation
|
||||
//= type=implication
|
||||
//# The IV's total length MUST match the IV length defined by the algorithm suite.
|
||||
$options['Iv'] = str_repeat("\1", $algorithmSuite->getIvLengthBytes());
|
||||
$messageId = $provider->generateIv(
|
||||
$this->getCipherOpenSslName(
|
||||
$algorithmSuite->getCipherName(),
|
||||
//= ../specification/s3-encryption/encryption.md#content-encryption
|
||||
//# The client MUST generate an IV or Message ID using the length of
|
||||
//# the IV or Message ID defined in the algorithm suite.
|
||||
$algorithmSuite->getKeyCommitmentSaltLengthBits()
|
||||
)
|
||||
);
|
||||
// Some providers modify materials description based on options
|
||||
if (isset($keys['UpdatedContext'])) {
|
||||
$materialsDescription["aws:x-amz-cek-alg"] = (string) $algorithmSuite->getId();
|
||||
}
|
||||
$commitingEncryptingArray = $this->getCommitingEncryptionStream(
|
||||
$plaintext,
|
||||
$keys['Plaintext'],
|
||||
$options,
|
||||
$messageId,
|
||||
$algorithmSuite
|
||||
);
|
||||
//= ../specification/s3-encryption/encryption.md#alg-aes-256-gcm-hkdf-sha512-commit-key
|
||||
//= type=implication
|
||||
//# The derived key commitment value MUST be set or returned from the encryption process
|
||||
//# such that it can be included in the content metadata.
|
||||
$commitmentKey = $commitingEncryptingArray[0];
|
||||
$encryptionStream = $commitingEncryptingArray[1];
|
||||
|
||||
// Populate envelope data
|
||||
$envelope[MetadataEnvelope::ENCRYPTED_DATA_KEY_V3] = $keys['Ciphertext'];
|
||||
unset($keys);
|
||||
|
||||
$envelope[MetadataEnvelope::CONTENT_CIPHER_V3] = $algorithmSuite->getId();
|
||||
// we are able to always set the encryption context in the envelope because PHP
|
||||
// only supports a KMS Material Provider.
|
||||
$envelope[MetadataEnvelope::ENCRYPTION_CONTEXT_V3] =
|
||||
json_encode($materialsDescription);
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#v3-only
|
||||
//# The Encryption Context value MUST be used for wrapping algorithm `kms+context` or `12`.
|
||||
$envelope[MetadataEnvelope::ENCRYPTED_DATA_KEY_ALGORITHM_V3] = '12';
|
||||
$envelope[MetadataEnvelope::KEY_COMMITMENT_V3] = $commitmentKey;
|
||||
$envelope[MetadataEnvelope::MESSAGE_ID_V3] = base64_encode($messageId);
|
||||
if (!MetadataEnvelope::isV3Envelope($envelope)) {
|
||||
throw new CryptoException("Error while writing metadata envelope."
|
||||
. " Not all required fields were set.");
|
||||
}
|
||||
|
||||
return $encryptionStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 AppendStream returns an AppendStream
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
protected function getNonCommittingEncryptingStream(
|
||||
Stream $plaintext,
|
||||
string $cek,
|
||||
array &$cipherOptions
|
||||
): AppendStream
|
||||
{
|
||||
// Only 'gcm' is supported for encryption currently
|
||||
switch ($cipherOptions['Cipher']) {
|
||||
//= ../specification/s3-encryption/encryption.md#content-encryption
|
||||
//= type=implication
|
||||
//# The S3EC MUST use the encryption algorithm configured during [client](./client.md) initialization.
|
||||
case 'gcm':
|
||||
$cipherOptions['TagLength'] = 16;
|
||||
$encryptClass = self::$encryptClasses['gcm'];
|
||||
//= ../specification/s3-encryption/encryption.md#alg-aes-256-gcm-iv12-tag16-no-kdf
|
||||
//= type=implication
|
||||
//# The client MUST initialize the cipher, or call an AES-GCM encryption API,
|
||||
//# with the plaintext data key, the generated IV, and the tag length defined
|
||||
//# in the Algorithm Suite when encrypting with ALG_AES_256_GCM_IV12_TAG16_NO_KDF.
|
||||
$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()
|
||||
]);
|
||||
//= ../specification/s3-encryption/encryption.md#alg-aes-256-gcm-iv12-tag16-no-kdf
|
||||
//= type=implication
|
||||
//# The client MUST append the GCM auth tag to the ciphertext if the underlying
|
||||
//# crypto provider does not do so automatically.
|
||||
$cipherOptions['Tag'] = $cipherTextStream->getTag();
|
||||
$appendStream->addStream(Psr7\Utils::streamFor($cipherOptions['Tag']));
|
||||
|
||||
return $appendStream;
|
||||
default:
|
||||
throw new CryptoException("Unsupported Cipher used for key commitment messages."
|
||||
. " Found {$cipherOptions["Cipher"]}. Only 'gcm' is supported.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @param string $messageId salt value used for key extraction step in the key
|
||||
* derivation process.
|
||||
* @param AlgorithmSuite $algorithmSuite options used for key commitment
|
||||
*
|
||||
* @return array returns an array with two elements as follows: [commitmentKey, AppendStream]
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
protected function getCommitingEncryptionStream(
|
||||
Stream $plaintext,
|
||||
string $dek,
|
||||
array &$cipherOptions,
|
||||
string $messageId,
|
||||
AlgorithmSuite $algorithmSuite
|
||||
): array
|
||||
{
|
||||
$algorithmSuiteIdAsBytes = pack('n', $algorithmSuite->getId());
|
||||
//= ../specification/s3-encryption/key-derivation.md#hkdf-operation
|
||||
//= type=implication
|
||||
//# - The input info MUST be a concatenation of the algorithm suite ID as bytes followed by the string DERIVEKEY as UTF8 encoded bytes.
|
||||
$derivedEncryptionKeyInfo = $algorithmSuiteIdAsBytes . "DERIVEKEY";
|
||||
//= ../specification/s3-encryption/key-derivation.md#hkdf-operation
|
||||
//= type=implication
|
||||
//# - The input info MUST be a concatenation of the algorithm suite ID as bytes followed by the string COMMITKEY as UTF8 encoded bytes.
|
||||
$commitmentKeyInfo = $algorithmSuiteIdAsBytes . "COMMITKEY";
|
||||
//= ../specification/s3-encryption/key-derivation.md#hkdf-operation
|
||||
//= type=implication
|
||||
//# - The length of the input keying material MUST equal the key derivation
|
||||
//# input length specified by the algorithm suite commit key derivation setting.
|
||||
if (strlen($dek) !== $algorithmSuite->getDerivationInputKeyLengthBytes()) {
|
||||
throw new CryptoException("Input Key Material length exceeds "
|
||||
. "key derivation input length specified by the algorithm suite.");
|
||||
}
|
||||
//= ../specification/s3-encryption/encryption.md#alg-aes-256-gcm-hkdf-sha512-commit-key
|
||||
//= type=implication
|
||||
//# The client MUST use HKDF to derive the key commitment value and
|
||||
//# the derived encrypting key as described in [Key Derivation](key-derivation.md).
|
||||
$cek = hash_hkdf(
|
||||
//= ../specification/s3-encryption/key-derivation.md#hkdf-operation
|
||||
//= type=implication
|
||||
//# - The hash function MUST be specified by the algorithm suite commitment settings.
|
||||
$algorithmSuite->getHashingAlgorithm(),
|
||||
//= ../specification/s3-encryption/key-derivation.md#hkdf-operation
|
||||
//= type=implication
|
||||
//# - The input keying material MUST be the plaintext data key (PDK) generated by the key provider.
|
||||
//= ../specification/s3-encryption/key-derivation.md#hkdf-operation
|
||||
//= type=implication
|
||||
//# - The DEK input pseudorandom key MUST be the output from the extract step.
|
||||
$dek,
|
||||
//= ../specification/s3-encryption/key-derivation.md#hkdf-operation
|
||||
//= type=implication
|
||||
//# - The length of the output keying material MUST equal the encryption key length specified by the algorithm suite encryption settings.
|
||||
$algorithmSuite->getDerivationOutputKeyLengthBytes(),
|
||||
$derivedEncryptionKeyInfo,
|
||||
//= ../specification/s3-encryption/key-derivation.md#hkdf-operation
|
||||
//= type=implication
|
||||
//# - The salt MUST be the Message ID with the length defined in the algorithm suite.
|
||||
$messageId
|
||||
);
|
||||
$commitmentKey = hash_hkdf(
|
||||
$algorithmSuite->getHashingAlgorithm(),
|
||||
//= ../specification/s3-encryption/key-derivation.md#hkdf-operation
|
||||
//= type=implication
|
||||
//# - The CK input pseudorandom key MUST be the output from the extract step.
|
||||
$dek,
|
||||
//= ../specification/s3-encryption/key-derivation.md#hkdf-operation
|
||||
//= type=implication
|
||||
//# - The length of the output keying material MUST equal the commit key length specified by the supported algorithm suites.
|
||||
$algorithmSuite->getCommitmentOutputKeyLengthBytes(),
|
||||
$commitmentKeyInfo,
|
||||
$messageId
|
||||
);
|
||||
|
||||
switch ($cipherOptions['Cipher']) {
|
||||
// Only 'gcm' is supported for encryption currently
|
||||
case 'gcm':
|
||||
$cipherOptions['TagLength'] = $algorithmSuite->getCipherTagLengthInBytes();
|
||||
$encryptClass = self::$encryptClasses[$algorithmSuite->getCipherName()];
|
||||
|
||||
if (!empty($cipherOptions['Aad'])) {
|
||||
trigger_error("'Aad' has been supplied for content encryption"
|
||||
. " with " . $encryptClass->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_NOTICE);
|
||||
}
|
||||
$cipherOptions['Aad'] = isset($cipherOptions['Aad'])
|
||||
? $cipherOptions['Aad'] + $algorithmSuiteIdAsBytes
|
||||
: $algorithmSuiteIdAsBytes;
|
||||
//= ../specification/s3-encryption/key-derivation.md#hkdf-operation
|
||||
//= type=implication
|
||||
//# The client MUST initialize the cipher, or call an AES-GCM encryption API,
|
||||
//# with the derived encryption key, an IV containing only bytes with the value 0x01,
|
||||
//# and the tag length defined in the Algorithm Suite when encrypting or
|
||||
//# decrypting with ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY.
|
||||
$cipherTextStream = new $encryptClass(
|
||||
$plaintext,
|
||||
$cek,
|
||||
$cipherOptions['Iv'],
|
||||
$cipherOptions['Aad'],
|
||||
$cipherOptions['TagLength'],
|
||||
$cipherOptions['KeySize']
|
||||
);
|
||||
|
||||
$appendStream = new AppendStream([
|
||||
$cipherTextStream->createStream()
|
||||
]);
|
||||
//= ../specification/s3-encryption/encryption.md#alg-aes-256-gcm-hkdf-sha512-commit-key
|
||||
//= type=implication
|
||||
//# The client MUST append the GCM auth tag to the ciphertext if the underlying
|
||||
//# crypto provider does not do so automatically.
|
||||
$cipherOptions['Tag'] = $cipherTextStream->getTag();
|
||||
$appendStream->addStream(Psr7\Utils::streamFor($cipherOptions['Tag']));
|
||||
|
||||
return [base64_encode($commitmentKey), $appendStream];
|
||||
default:
|
||||
throw new CryptoException("Unsupported Cipher used for content encryption");
|
||||
}
|
||||
}
|
||||
}
|
||||
121
vendor/aws/aws-sdk-php/src/Crypto/KmsMaterialsProvider.php
vendored
Normal file
121
vendor/aws/aws-sdk-php/src/Crypto/KmsMaterialsProvider.php
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
namespace Aws\Crypto;
|
||||
|
||||
use Aws\Kms\KmsClient;
|
||||
|
||||
/**
|
||||
* Uses KMS to supply materials for encrypting and decrypting data.
|
||||
*
|
||||
* Legacy implementation that supports legacy S3EncryptionClient and
|
||||
* S3EncryptionMultipartUploader, which use an older encryption workflow. Use
|
||||
* KmsMaterialsProviderV2 with S3EncryptionClientV2 or
|
||||
* S3EncryptionMultipartUploaderV2 if possible.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
class KmsMaterialsProvider extends MaterialsProvider implements MaterialsProviderInterface
|
||||
{
|
||||
const WRAP_ALGORITHM_NAME = 'kms';
|
||||
|
||||
private $kmsClient;
|
||||
private $kmsKeyId;
|
||||
|
||||
/**
|
||||
* @param KmsClient $kmsClient A KMS Client for use encrypting and
|
||||
* decrypting keys.
|
||||
* @param string $kmsKeyId The private KMS key id to be used for encrypting
|
||||
* and decrypting keys.
|
||||
*/
|
||||
public function __construct(
|
||||
KmsClient $kmsClient,
|
||||
$kmsKeyId = null
|
||||
) {
|
||||
$this->kmsClient = $kmsClient;
|
||||
$this->kmsKeyId = $kmsKeyId;
|
||||
}
|
||||
|
||||
public function fromDecryptionEnvelope(MetadataEnvelope $envelope)
|
||||
{
|
||||
if (empty($envelope[MetadataEnvelope::MATERIALS_DESCRIPTION_HEADER])) {
|
||||
throw new \RuntimeException('Not able to detect the materials description.');
|
||||
}
|
||||
|
||||
$materialsDescription = json_decode(
|
||||
$envelope[MetadataEnvelope::MATERIALS_DESCRIPTION_HEADER],
|
||||
true
|
||||
);
|
||||
|
||||
if (empty($materialsDescription['kms_cmk_id'])
|
||||
&& empty($materialsDescription['aws:x-amz-cek-alg'])) {
|
||||
throw new \RuntimeException('Not able to detect kms_cmk_id (legacy'
|
||||
. ' implementation) or aws:x-amz-cek-alg (current implementation)'
|
||||
. ' from kms materials description.');
|
||||
}
|
||||
|
||||
return new self(
|
||||
$this->kmsClient,
|
||||
isset($materialsDescription['kms_cmk_id'])
|
||||
? $materialsDescription['kms_cmk_id']
|
||||
: null
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The KMS key id for use in matching this Provider to its keys,
|
||||
* consistently with other SDKs as 'kms_cmk_id'.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getMaterialsDescription()
|
||||
{
|
||||
return ['kms_cmk_id' => $this->kmsKeyId];
|
||||
}
|
||||
|
||||
public function getWrapAlgorithmName()
|
||||
{
|
||||
return self::WRAP_ALGORITHM_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a content encryption key (CEK) and description to return an encrypted
|
||||
* key by using KMS' Encrypt API.
|
||||
*
|
||||
* @param string $unencryptedCek Key for use in encrypting other data
|
||||
* that itself needs to be encrypted by the
|
||||
* Provider.
|
||||
* @param string $materialDescription Material Description for use in
|
||||
* encrypting the $cek.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function encryptCek($unencryptedCek, $materialDescription)
|
||||
{
|
||||
$encryptedDataKey = $this->kmsClient->encrypt([
|
||||
'Plaintext' => $unencryptedCek,
|
||||
'KeyId' => $this->kmsKeyId,
|
||||
'EncryptionContext' => $materialDescription
|
||||
]);
|
||||
return base64_encode($encryptedDataKey['CiphertextBlob']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes an encrypted content encryption key (CEK) and material description
|
||||
* for use decrypting the key by using KMS' Decrypt API.
|
||||
*
|
||||
* @param string $encryptedCek Encrypted key to be decrypted by the Provider
|
||||
* for use decrypting other data.
|
||||
* @param string $materialDescription Material Description for use in
|
||||
* encrypting the $cek.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function decryptCek($encryptedCek, $materialDescription)
|
||||
{
|
||||
$result = $this->kmsClient->decrypt([
|
||||
'CiphertextBlob' => $encryptedCek,
|
||||
'EncryptionContext' => $materialDescription
|
||||
]);
|
||||
|
||||
return $result['Plaintext'];
|
||||
}
|
||||
}
|
||||
100
vendor/aws/aws-sdk-php/src/Crypto/KmsMaterialsProviderV2.php
vendored
Normal file
100
vendor/aws/aws-sdk-php/src/Crypto/KmsMaterialsProviderV2.php
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
namespace Aws\Crypto;
|
||||
|
||||
use Aws\Exception\CryptoException;
|
||||
use Aws\Kms\KmsClient;
|
||||
|
||||
/**
|
||||
* Uses KMS to supply materials for encrypting and decrypting data. This
|
||||
* V2 implementation should be used with the V2 encryption clients (i.e.
|
||||
* S3EncryptionClientV2).
|
||||
*/
|
||||
class KmsMaterialsProviderV2 extends MaterialsProviderV2 implements MaterialsProviderInterfaceV2
|
||||
{
|
||||
const WRAP_ALGORITHM_NAME = 'kms+context';
|
||||
|
||||
private $kmsClient;
|
||||
private $kmsKeyId;
|
||||
|
||||
/**
|
||||
* @param KmsClient $kmsClient A KMS Client for use encrypting and
|
||||
* decrypting keys.
|
||||
* @param string $kmsKeyId The private KMS key id to be used for encrypting
|
||||
* and decrypting keys.
|
||||
*/
|
||||
public function __construct(
|
||||
KmsClient $kmsClient,
|
||||
$kmsKeyId = null
|
||||
) {
|
||||
$this->kmsClient = $kmsClient;
|
||||
$this->kmsKeyId = $kmsKeyId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getWrapAlgorithmName()
|
||||
{
|
||||
return self::WRAP_ALGORITHM_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function decryptCek($encryptedCek, $materialDescription, $options)
|
||||
{
|
||||
$params = [
|
||||
'CiphertextBlob' => $encryptedCek,
|
||||
'EncryptionContext' => $materialDescription
|
||||
];
|
||||
if (empty($options['@KmsAllowDecryptWithAnyCmk'])) {
|
||||
if (empty($this->kmsKeyId)) {
|
||||
throw new CryptoException('KMS CMK ID was not specified and the'
|
||||
. ' operation is not opted-in to attempting to use any valid'
|
||||
. ' CMK it discovers. Please specify a CMK ID, or explicitly'
|
||||
. ' enable attempts to use any valid KMS CMK with the'
|
||||
. ' @KmsAllowDecryptWithAnyCmk option.');
|
||||
}
|
||||
$params['KeyId'] = $this->kmsKeyId;
|
||||
}
|
||||
|
||||
$result = $this->kmsClient->decrypt($params);
|
||||
return $result['Plaintext'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function generateCek($keySize, $context, $options)
|
||||
{
|
||||
if (empty($this->kmsKeyId)) {
|
||||
throw new CryptoException('A KMS key id is required for encryption'
|
||||
. ' with KMS keywrap. Use a KmsMaterialsProviderV2 that has been'
|
||||
. ' instantiated with a KMS key id.');
|
||||
}
|
||||
$options = array_change_key_case($options);
|
||||
if (!isset($options['@kmsencryptioncontext'])
|
||||
|| !is_array($options['@kmsencryptioncontext'])
|
||||
) {
|
||||
throw new CryptoException("'@KmsEncryptionContext' is a"
|
||||
. " required argument when using KmsMaterialsProviderV2, and"
|
||||
. " must be an associative array (or empty array).");
|
||||
}
|
||||
if (isset($options['@kmsencryptioncontext']['aws:x-amz-cek-alg'])) {
|
||||
throw new CryptoException("Conflict in reserved @KmsEncryptionContext"
|
||||
. " key aws:x-amz-cek-alg. This value is reserved for the S3"
|
||||
. " Encryption Client and cannot be set by the user.");
|
||||
}
|
||||
$context = array_merge($options['@kmsencryptioncontext'], $context);
|
||||
$result = $this->kmsClient->generateDataKey([
|
||||
'KeyId' => $this->kmsKeyId,
|
||||
'KeySpec' => "AES_{$keySize}",
|
||||
'EncryptionContext' => $context
|
||||
]);
|
||||
return [
|
||||
'Plaintext' => $result['Plaintext'],
|
||||
'Ciphertext' => base64_encode($result['CiphertextBlob']),
|
||||
'UpdatedContext' => $context
|
||||
];
|
||||
}
|
||||
}
|
||||
159
vendor/aws/aws-sdk-php/src/Crypto/KmsMaterialsProviderV3.php
vendored
Normal file
159
vendor/aws/aws-sdk-php/src/Crypto/KmsMaterialsProviderV3.php
vendored
Normal file
@@ -0,0 +1,159 @@
|
||||
<?php
|
||||
namespace Aws\Crypto;
|
||||
|
||||
use Aws\Exception\CryptoException;
|
||||
use Aws\Kms\KmsClient;
|
||||
|
||||
/**
|
||||
* Uses KMS to supply materials for encrypting and decrypting data. This
|
||||
* V2 implementation should be used with the V2 encryption clients (i.e.
|
||||
* S3EncryptionClientV2).
|
||||
*/
|
||||
class KmsMaterialsProviderV3 extends MaterialsProviderV3 implements MaterialsProviderInterfaceV3
|
||||
{
|
||||
const WRAP_ALGORITHM_NAME = 'kms+context';
|
||||
private KmsClient $kmsClient;
|
||||
private ?string $kmsKeyId;
|
||||
|
||||
/**
|
||||
* @param KmsClient $kmsClient A KMS Client for use encrypting and
|
||||
* decrypting keys.
|
||||
* @param string $kmsKeyId The private KMS key id to be used for encrypting
|
||||
* and decrypting keys.
|
||||
*/
|
||||
public function __construct(
|
||||
KmsClient $kmsClient,
|
||||
?string $kmsKeyId = null
|
||||
) {
|
||||
$this->kmsClient = $kmsClient;
|
||||
$this->kmsKeyId = $kmsKeyId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getWrapAlgorithmName(): string
|
||||
{
|
||||
return self::WRAP_ALGORITHM_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function decryptCek(
|
||||
string $encryptedCek,
|
||||
array $materialDescription,
|
||||
array $options
|
||||
): string
|
||||
{
|
||||
$options = array_change_key_case($options);
|
||||
$encryptionContext = null;
|
||||
|
||||
// no encryption context was provided we will use the one in the metadata
|
||||
if (!isset($options['@kmsencryptioncontext'])) {
|
||||
$encryptionContext = $materialDescription;
|
||||
} else {
|
||||
// encryption context was passed in, we have to make sure it is an array
|
||||
// and that the reserved keywords were not used
|
||||
if (!is_array($options['@kmsencryptioncontext'])) {
|
||||
throw new CryptoException("'When using @KmsMaterialsProviderV3, it"
|
||||
. " must be an associative array (or empty array).");
|
||||
}
|
||||
|
||||
if (isset($options['@kmsencryptioncontext']['aws:x-amz-cek-alg'])) {
|
||||
throw new CryptoException("Conflict in reserved @KmsEncryptionContext"
|
||||
. " key aws:x-amz-cek-alg. This value is reserved for the S3"
|
||||
. " Encryption Client and cannot be set by the user.");
|
||||
}
|
||||
|
||||
if (isset($options['@kmsencryptioncontext']['kms_cmk_id'])) {
|
||||
throw new CryptoException("Conflict in reserved @KmsEncryptionContext"
|
||||
. " key kms_cmk_id. This value is reserved for the S3"
|
||||
. " Encryption Client and cannot be set by the user.");
|
||||
}
|
||||
//= specification/s3-encryption/materials/s3-kms-keyring.md#kms-context
|
||||
//= type=implication
|
||||
//# When decrypting using Kms+Context mode, the KmsKeyring MUST validate the provided (request) encryption context with the stored (materials) encryption context.
|
||||
// We are validating the encryption context to match S3EC V2 behavior
|
||||
// Refer to KMSMaterialsHandler in the V2 client for details
|
||||
$materialsDescriptionContextCopy = $materialDescription;
|
||||
unset($materialsDescriptionContextCopy["aws:x-amz-cek-alg"]);
|
||||
unset($materialsDescriptionContextCopy["kms_cmk_id"]);
|
||||
|
||||
$requestEncryptionContext = $options['@kmsencryptioncontext'];
|
||||
//= specification/s3-encryption/materials/s3-kms-keyring.md#kms-context
|
||||
//= type=implication
|
||||
//# The stored encryption context with the two reserved keys removed MUST match the provided encryption context.
|
||||
if ($materialsDescriptionContextCopy !== $requestEncryptionContext) {
|
||||
//= specification/s3-encryption/materials/s3-kms-keyring.md#kms-context
|
||||
//= type=implication
|
||||
//# If the stored encryption context with the two reserved keys removed does not match the provided encryption context, the KmsKeyring MUST throw an exception.
|
||||
throw new CryptoException("Provided encryption context does not match information retrieved from S3");
|
||||
}
|
||||
$encryptionContext = $materialDescription;
|
||||
}
|
||||
$params = [
|
||||
'CiphertextBlob' => $encryptedCek,
|
||||
'EncryptionContext' => $encryptionContext
|
||||
];
|
||||
|
||||
if (empty($options['@kmsallowdecryptwithanycmk'])) {
|
||||
if (empty($this->kmsKeyId)) {
|
||||
throw new CryptoException('KMS CMK ID was not specified and the'
|
||||
. ' operation is not opted-in to attempting to use any valid'
|
||||
. ' CMK it discovers. Please specify a CMK ID, or explicitly'
|
||||
. ' enable attempts to use any valid KMS CMK with the'
|
||||
. ' @KmsAllowDecryptWithAnyCmk option.');
|
||||
}
|
||||
$params['KeyId'] = $this->kmsKeyId;
|
||||
}
|
||||
|
||||
$result = $this->kmsClient->decrypt($params);
|
||||
|
||||
return $result['Plaintext'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function generateCek($keySize, $context, $options): array
|
||||
{
|
||||
if (empty($this->kmsKeyId)) {
|
||||
throw new CryptoException('A KMS key id is required for encryption'
|
||||
. ' with KMS keywrap. Use a KmsMaterialsProviderV2 that has been'
|
||||
. ' instantiated with a KMS key id.');
|
||||
}
|
||||
$options = array_change_key_case($options);
|
||||
if (!isset($options['@kmsencryptioncontext'])
|
||||
|| !is_array($options['@kmsencryptioncontext'])
|
||||
) {
|
||||
throw new CryptoException("'@KmsEncryptionContext' is a"
|
||||
. " required argument when using KmsMaterialsProviderV3, and"
|
||||
. " must be an associative array (or empty array).");
|
||||
}
|
||||
|
||||
if (isset($options['@kmsencryptioncontext']['aws:x-amz-cek-alg'])) {
|
||||
throw new CryptoException("Conflict in reserved @KmsEncryptionContext"
|
||||
. " key aws:x-amz-cek-alg. This value is reserved for the S3"
|
||||
. " Encryption Client and cannot be set by the user.");
|
||||
}
|
||||
|
||||
if (isset($options['@kmsencryptioncontext']['kms_cmk_id'])) {
|
||||
throw new CryptoException("Conflict in reserved @KmsEncryptionContext"
|
||||
. " key kms_cmk_id. This value is reserved for the S3"
|
||||
. " Encryption Client and cannot be set by the user.");
|
||||
}
|
||||
$context = array_merge($options['@kmsencryptioncontext'], $context);
|
||||
$result = $this->kmsClient->generateDataKey([
|
||||
'KeyId' => $this->kmsKeyId,
|
||||
'KeySpec' => "AES_{$keySize}",
|
||||
'EncryptionContext' => $context
|
||||
]);
|
||||
|
||||
return [
|
||||
'Plaintext' => $result['Plaintext'],
|
||||
'Ciphertext' => base64_encode($result['CiphertextBlob']),
|
||||
'UpdatedContext' => $context
|
||||
];
|
||||
}
|
||||
}
|
||||
105
vendor/aws/aws-sdk-php/src/Crypto/MaterialsProvider.php
vendored
Normal file
105
vendor/aws/aws-sdk-php/src/Crypto/MaterialsProvider.php
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
namespace Aws\Crypto;
|
||||
|
||||
abstract class MaterialsProvider implements MaterialsProviderInterface
|
||||
{
|
||||
private static $supportedKeySizes = [
|
||||
128 => true,
|
||||
192 => true,
|
||||
256 => true,
|
||||
];
|
||||
|
||||
/**
|
||||
* Returns if the requested size is supported by AES.
|
||||
*
|
||||
* @param int $keySize Size of the requested key in bits.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isSupportedKeySize($keySize)
|
||||
{
|
||||
return isset(self::$supportedKeySizes[$keySize]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs further initialization of the MaterialsProvider based on the
|
||||
* data inside the MetadataEnvelope.
|
||||
*
|
||||
* @param MetadataEnvelope $envelope A storage envelope for encryption
|
||||
* metadata to be read from.
|
||||
*
|
||||
* @return MaterialsProvider
|
||||
*
|
||||
* @throws \RuntimeException Thrown when there is an empty or improperly
|
||||
* formed materials description in the envelope.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
abstract public function fromDecryptionEnvelope(MetadataEnvelope $envelope);
|
||||
|
||||
/**
|
||||
* Returns the material description for this Provider so it can be verified
|
||||
* by encryption mechanisms.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function getMaterialsDescription();
|
||||
|
||||
/**
|
||||
* Returns the wrap algorithm name for this Provider.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function getWrapAlgorithmName();
|
||||
|
||||
/**
|
||||
* Takes a content encryption key (CEK) and description to return an
|
||||
* encrypted key according to the Provider's specifications.
|
||||
*
|
||||
* @param string $unencryptedCek Key for use in encrypting other data
|
||||
* that itself needs to be encrypted by the
|
||||
* Provider.
|
||||
* @param string $materialDescription Material Description for use in
|
||||
* encrypting the $cek.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function encryptCek($unencryptedCek, $materialDescription);
|
||||
|
||||
/**
|
||||
* Takes an encrypted content encryption key (CEK) and material description
|
||||
* for use decrypting the key according to the Provider's specifications.
|
||||
*
|
||||
* @param string $encryptedCek Encrypted key to be decrypted by the Provider
|
||||
* for use decrypting other data.
|
||||
* @param string $materialDescription Material Description for use in
|
||||
* encrypting the $cek.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function decryptCek($encryptedCek, $materialDescription);
|
||||
|
||||
/**
|
||||
* @param string $keySize Length of a cipher key in bits for generating a
|
||||
* random content encryption key (CEK).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function generateCek($keySize)
|
||||
{
|
||||
return openssl_random_pseudo_bytes($keySize / 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $openSslName Cipher OpenSSL name to use for generating
|
||||
* an initialization vector.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function generateIv($openSslName)
|
||||
{
|
||||
return openssl_random_pseudo_bytes(
|
||||
openssl_cipher_iv_length($openSslName)
|
||||
);
|
||||
}
|
||||
}
|
||||
61
vendor/aws/aws-sdk-php/src/Crypto/MaterialsProviderInterface.php
vendored
Normal file
61
vendor/aws/aws-sdk-php/src/Crypto/MaterialsProviderInterface.php
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
namespace Aws\Crypto;
|
||||
|
||||
interface MaterialsProviderInterface
|
||||
{
|
||||
/**
|
||||
* Returns if the requested size is supported by AES.
|
||||
*
|
||||
* @param int $keySize Size of the requested key in bits.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isSupportedKeySize($keySize);
|
||||
|
||||
/**
|
||||
* Performs further initialization of the MaterialsProvider based on the
|
||||
* data inside the MetadataEnvelope.
|
||||
*
|
||||
* @param MetadataEnvelope $envelope A storage envelope for encryption
|
||||
* metadata to be read from.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function fromDecryptionEnvelope(MetadataEnvelope $envelope);
|
||||
|
||||
/**
|
||||
* Returns the wrap algorithm name for this Provider.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getWrapAlgorithmName();
|
||||
|
||||
/**
|
||||
* Takes an encrypted content encryption key (CEK) and material description
|
||||
* for use decrypting the key according to the Provider's specifications.
|
||||
*
|
||||
* @param string $encryptedCek Encrypted key to be decrypted by the Provider
|
||||
* for use decrypting other data.
|
||||
* @param string $materialDescription Material Description for use in
|
||||
* encrypting the $cek.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function decryptCek($encryptedCek, $materialDescription);
|
||||
|
||||
/**
|
||||
* @param string $keySize Length of a cipher key in bits for generating a
|
||||
* random content encryption key (CEK).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function generateCek($keySize);
|
||||
|
||||
/**
|
||||
* @param string $openSslName Cipher OpenSSL name to use for generating
|
||||
* an initialization vector.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function generateIv($openSslName);
|
||||
}
|
||||
53
vendor/aws/aws-sdk-php/src/Crypto/MaterialsProviderInterfaceV2.php
vendored
Normal file
53
vendor/aws/aws-sdk-php/src/Crypto/MaterialsProviderInterfaceV2.php
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
namespace Aws\Crypto;
|
||||
|
||||
interface MaterialsProviderInterfaceV2
|
||||
{
|
||||
/**
|
||||
* Returns if the requested size is supported by AES.
|
||||
*
|
||||
* @param int $keySize Size of the requested key in bits.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isSupportedKeySize($keySize);
|
||||
|
||||
/**
|
||||
* Returns the wrap algorithm name for this Provider.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getWrapAlgorithmName();
|
||||
|
||||
/**
|
||||
* Takes an encrypted content encryption key (CEK) and material description
|
||||
* for use decrypting the key according to the Provider's specifications.
|
||||
*
|
||||
* @param string $encryptedCek Encrypted key to be decrypted by the Provider
|
||||
* for use decrypting other data.
|
||||
* @param string $materialDescription Material Description for use in
|
||||
* decrypting the CEK.
|
||||
* @param array $options Options for use in decrypting the CEK.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function decryptCek($encryptedCek, $materialDescription, $options);
|
||||
|
||||
/**
|
||||
* @param string $keySize Length of a cipher key in bits for generating a
|
||||
* random content encryption key (CEK).
|
||||
* @param array $context Context map needed for key encryption
|
||||
* @param array $options Additional options to be used in CEK generation
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function generateCek($keySize, $context, $options);
|
||||
|
||||
/**
|
||||
* @param string $openSslName Cipher OpenSSL name to use for generating
|
||||
* an initialization vector.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function generateIv($openSslName);
|
||||
}
|
||||
61
vendor/aws/aws-sdk-php/src/Crypto/MaterialsProviderInterfaceV3.php
vendored
Normal file
61
vendor/aws/aws-sdk-php/src/Crypto/MaterialsProviderInterfaceV3.php
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
namespace Aws\Crypto;
|
||||
|
||||
interface MaterialsProviderInterfaceV3
|
||||
{
|
||||
/**
|
||||
* Returns if the requested size is supported by AES.
|
||||
*
|
||||
* @param int $keySize Size of the requested key in bits.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isSupportedKeySize(int $keySize): bool;
|
||||
|
||||
/**
|
||||
* Returns the wrap algorithm name for this Provider.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getWrapAlgorithmName(): string;
|
||||
|
||||
/**
|
||||
* Takes an encrypted content encryption key (CEK) and material description
|
||||
* for use decrypting the key according to the Provider's specifications.
|
||||
*
|
||||
* @param string $encryptedCek Encrypted key to be decrypted by the Provider
|
||||
* for use decrypting other data.
|
||||
* @param array $materialDescription Material Description for use in
|
||||
* decrypting the CEK.
|
||||
* @param AlgorithmSuite $algorithmSuite AlgorithmSuite for use in decrypting the CEK.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function decryptCek(
|
||||
string $encryptedCek,
|
||||
array $materialDescription,
|
||||
array $options
|
||||
): string;
|
||||
|
||||
/**
|
||||
* @param string $keySize Length of a cipher key in bits for generating a
|
||||
* random content encryption key (CEK).
|
||||
* @param array $context Context map needed for key encryption
|
||||
* @param array $options Additional options to be used in CEK generation
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function generateCek(
|
||||
string $keySize,
|
||||
array $context,
|
||||
array $options
|
||||
): array;
|
||||
|
||||
/**
|
||||
* @param string $openSslName Cipher OpenSSL name to use for generating
|
||||
* an initialization vector.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function generateIv(string $openSslName): string;
|
||||
}
|
||||
66
vendor/aws/aws-sdk-php/src/Crypto/MaterialsProviderV2.php
vendored
Normal file
66
vendor/aws/aws-sdk-php/src/Crypto/MaterialsProviderV2.php
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
namespace Aws\Crypto;
|
||||
|
||||
abstract class MaterialsProviderV2 implements MaterialsProviderInterfaceV2
|
||||
{
|
||||
private static $supportedKeySizes = [
|
||||
128 => true,
|
||||
256 => true,
|
||||
];
|
||||
|
||||
/**
|
||||
* Returns if the requested size is supported by AES.
|
||||
*
|
||||
* @param int $keySize Size of the requested key in bits.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isSupportedKeySize($keySize)
|
||||
{
|
||||
return isset(self::$supportedKeySizes[$keySize]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the wrap algorithm name for this Provider.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function getWrapAlgorithmName();
|
||||
|
||||
/**
|
||||
* Takes an encrypted content encryption key (CEK) and material description
|
||||
* for use decrypting the key according to the Provider's specifications.
|
||||
*
|
||||
* @param string $encryptedCek Encrypted key to be decrypted by the Provider
|
||||
* for use decrypting other data.
|
||||
* @param string $materialDescription Material Description for use in
|
||||
* decrypting the CEK.
|
||||
* @param string $options Options for use in decrypting the CEK.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function decryptCek($encryptedCek, $materialDescription, $options);
|
||||
|
||||
/**
|
||||
* @param string $keySize Length of a cipher key in bits for generating a
|
||||
* random content encryption key (CEK).
|
||||
* @param array $context Context map needed for key encryption
|
||||
* @param array $options Additional options to be used in CEK generation
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract public function generateCek($keySize, $context, $options);
|
||||
|
||||
/**
|
||||
* @param string $openSslName Cipher OpenSSL name to use for generating
|
||||
* an initialization vector.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function generateIv($openSslName)
|
||||
{
|
||||
return openssl_random_pseudo_bytes(
|
||||
openssl_cipher_iv_length($openSslName)
|
||||
);
|
||||
}
|
||||
}
|
||||
90
vendor/aws/aws-sdk-php/src/Crypto/MaterialsProviderV3.php
vendored
Normal file
90
vendor/aws/aws-sdk-php/src/Crypto/MaterialsProviderV3.php
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
namespace Aws\Crypto;
|
||||
|
||||
use Aws\Exception\CryptoException;
|
||||
|
||||
abstract class MaterialsProviderV3 implements MaterialsProviderInterfaceV3
|
||||
{
|
||||
private static array $supportedKeySizes = [
|
||||
256 => true
|
||||
];
|
||||
|
||||
/**
|
||||
* Returns if the requested size is supported by AES.
|
||||
*
|
||||
* @param int $keySize Size of the requested key in bits.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isSupportedKeySize(int $keySize): bool
|
||||
{
|
||||
return isset(self::$supportedKeySizes[$keySize]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the wrap algorithm name for this Provider.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function getWrapAlgorithmName(): string;
|
||||
|
||||
/**
|
||||
* Takes an encrypted content encryption key (CEK) and material description
|
||||
* for use decrypting the key according to the Provider's specifications.
|
||||
*
|
||||
* @param string $encryptedCek Encrypted key to be decrypted by the Provider
|
||||
* for use decrypting other data.
|
||||
* @param array $materialDescription Material Description for use in
|
||||
* decrypting the CEK.
|
||||
* @param array $options Options for use in decrypting the CEK.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function decryptCek(
|
||||
string $encryptedCek,
|
||||
array $materialDescription,
|
||||
array $options
|
||||
): string;
|
||||
|
||||
/**
|
||||
* @param string $keySize Length of a cipher key in bits for generating a
|
||||
* random content encryption key (CEK).
|
||||
* @param array $context Context map needed for key encryption
|
||||
* @param array $options Additional options to be used in CEK generation
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract public function generateCek(
|
||||
string $keySize,
|
||||
array $context,
|
||||
array $options
|
||||
): array;
|
||||
|
||||
/**
|
||||
* @param string $openSslName Cipher OpenSSL name to use for generating
|
||||
* an initialization vector.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function generateIv(string $openSslName): string
|
||||
{
|
||||
$iv = null;
|
||||
$cstrong = null;
|
||||
|
||||
if ($openSslName === "aes-96-gcm") {
|
||||
$iv = openssl_random_pseudo_bytes(12, $cstrong);
|
||||
} else if ($openSslName === "aes-224-gcm") {
|
||||
$iv = openssl_random_pseudo_bytes(28, $cstrong);
|
||||
} else {
|
||||
$iv = openssl_random_pseudo_bytes(
|
||||
openssl_cipher_iv_length($openSslName),
|
||||
$cstrong
|
||||
);
|
||||
}
|
||||
if (!$cstrong) {
|
||||
throw new CryptoException("No strong cryptographic source available to generate a random IV.");
|
||||
}
|
||||
|
||||
return $iv;
|
||||
}
|
||||
}
|
||||
207
vendor/aws/aws-sdk-php/src/Crypto/MetadataEnvelope.php
vendored
Normal file
207
vendor/aws/aws-sdk-php/src/Crypto/MetadataEnvelope.php
vendored
Normal file
@@ -0,0 +1,207 @@
|
||||
<?php
|
||||
namespace Aws\Crypto;
|
||||
|
||||
use Aws\HasDataTrait;
|
||||
use \ArrayAccess;
|
||||
use \IteratorAggregate;
|
||||
use \InvalidArgumentException;
|
||||
use \JsonSerializable;
|
||||
|
||||
/**
|
||||
* Stores encryption metadata for reading and writing.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class MetadataEnvelope implements ArrayAccess, IteratorAggregate, JsonSerializable
|
||||
{
|
||||
use HasDataTrait;
|
||||
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
|
||||
//# The "x-amz-" prefix denotes that the metadata is owned by an Amazon product
|
||||
//# and MUST be prepended to all S3EC metadata mapkeys.
|
||||
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
|
||||
//# - The mapkey "x-amz-key-v2" MUST be present for V2 format objects.
|
||||
const CONTENT_KEY_V2_HEADER = 'x-amz-key-v2';
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
|
||||
//= type=implication
|
||||
//# - This mapkey ("x-amz-3") SHOULD be represented by a constant named "ENCRYPTED_DATA_KEY_V3" or similar in the implementation code.
|
||||
const ENCRYPTED_DATA_KEY_V3 = 'x-amz-3';
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
|
||||
//# - The mapkey "x-amz-iv" MUST be present for V1 format objects.
|
||||
const IV_HEADER = 'x-amz-iv';
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
|
||||
//# - The mapkey "x-amz-matdesc" MUST be present for V1 format objects.
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
|
||||
//# - The mapkey "x-amz-matdesc" MUST be present for V2 format objects.
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
|
||||
//# - The mapkey "x-amz-iv" MUST be present for V2 format objects.
|
||||
const MATERIALS_DESCRIPTION_HEADER = 'x-amz-matdesc';
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
|
||||
//= type=implication
|
||||
//# - This mapkey ("x-amz-m") SHOULD be represented by a constant named "MAT_DESC_V3" or similar in the implementation code.
|
||||
const MAT_DESC_V3 = 'x-amz-m';
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
|
||||
//# - The mapkey "x-amz-wrap-alg" MUST be present for V2 format objects.
|
||||
const KEY_WRAP_ALGORITHM_HEADER = 'x-amz-wrap-alg';
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
|
||||
//= type=implication
|
||||
//# - This mapkey ("x-amz-w") SHOULD be represented by a constant named "ENCRYPTED_DATA_KEY_ALGORITHM_V3" or similar in the implementation code.
|
||||
const ENCRYPTED_DATA_KEY_ALGORITHM_V3 = 'x-amz-w';
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
|
||||
//# - The mapkey "x-amz-cek-alg" MUST be present for V2 format objects.
|
||||
const CONTENT_CRYPTO_SCHEME_HEADER = 'x-amz-cek-alg';
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
|
||||
//= type=implication
|
||||
//# - This mapkey ("x-amz-c") SHOULD be represented by a constant named "CONTENT_CIPHER_V3" or similar in the implementation code.
|
||||
const CONTENT_CIPHER_V3 = 'x-amz-c';
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
|
||||
//# - The mapkey "x-amz-tag-len" MUST be present for V2 format objects.
|
||||
const CRYPTO_TAG_LENGTH_HEADER = 'x-amz-tag-len';
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
|
||||
//# - The mapkey "x-amz-unencrypted-content-length" SHOULD be present for V1 format objects.
|
||||
const UNENCRYPTED_CONTENT_LENGTH_HEADER = 'x-amz-unencrypted-content-length';
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
|
||||
//= type=implication
|
||||
//# - This mapkey ("x-amz-t") SHOULD be represented by a constant named "ENCRYPTION_CONTEXT_V3" or similar in the implementation code.
|
||||
const ENCRYPTION_CONTEXT_V3 = 'x-amz-t';
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
|
||||
//= type=implication
|
||||
//# - This mapkey ("x-amz-d") SHOULD be represented by a constant named "KEY_COMMITMENT_V3" or similar in the implementation code.
|
||||
const KEY_COMMITMENT_V3 = 'x-amz-d';
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
|
||||
//= type=implication
|
||||
//# - This mapkey ("x-amz-i") SHOULD be represented by a constant named "MESSAGE_ID_V3" or similar in the implementation code.
|
||||
const MESSAGE_ID_V3 = 'x-amz-i';
|
||||
|
||||
private static $constants = [];
|
||||
|
||||
public static function getConstantValues()
|
||||
{
|
||||
if (empty(self::$constants)) {
|
||||
$reflection = new \ReflectionClass(static::class);
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
|
||||
//# The "x-amz-meta-" prefix is automatically added by the S3 server and MUST NOT be included in implementation code.
|
||||
foreach (array_values($reflection->getConstants()) as $constant) {
|
||||
self::$constants[$constant] = true;
|
||||
}
|
||||
}
|
||||
|
||||
return array_keys(self::$constants);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetSet($name, $value)
|
||||
{
|
||||
$constants = self::getConstantValues();
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#determining-s3ec-object-status
|
||||
//# In general, if there is any deviation from the above format, with the exception of additional unrelated mapkeys, then the S3EC SHOULD throw an exception.
|
||||
if (is_null($name) || !in_array($name, $constants)) {
|
||||
throw new InvalidArgumentException('MetadataEnvelope fields must'
|
||||
. ' must match a predefined offset; use the header constants.');
|
||||
}
|
||||
|
||||
$this->data[$name] = $value;
|
||||
}
|
||||
|
||||
#[\ReturnTypeWillChange]
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
public static function isV2Envelope(MetadataEnvelope $envelope): bool
|
||||
{
|
||||
if (!isset($envelope[MetadataEnvelope::CONTENT_KEY_V2_HEADER])
|
||||
|| !isset($envelope[MetadataEnvelope::MATERIALS_DESCRIPTION_HEADER])
|
||||
|| !isset($envelope[MetadataEnvelope::IV_HEADER])
|
||||
|| !isset($envelope[MetadataEnvelope::KEY_WRAP_ALGORITHM_HEADER])
|
||||
|| !isset($envelope[MetadataEnvelope::CONTENT_CRYPTO_SCHEME_HEADER])
|
||||
|| !isset($envelope[MetadataEnvelope::CRYPTO_TAG_LENGTH_HEADER])
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function isV1Envelope(MetadataEnvelope $envelope): bool
|
||||
{
|
||||
if (!isset($envelope[MetadataEnvelope::CONTENT_KEY_V2_HEADER])
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
|
||||
//# - The mapkey "x-amz-matdesc" MUST be present for V1 format objects.
|
||||
|| !isset($envelope[MetadataEnvelope::MATERIALS_DESCRIPTION_HEADER])
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
|
||||
//# - The mapkey "x-amz-iv" MUST be present for V1 format objects.
|
||||
|| !isset($envelope[MetadataEnvelope::IV_HEADER])
|
||||
|| !isset($envelope[MetadataEnvelope::KEY_WRAP_ALGORITHM_HEADER])
|
||||
|| !isset($envelope[MetadataEnvelope::CONTENT_CRYPTO_SCHEME_HEADER])
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
|
||||
//# - The mapkey "x-amz-unencrypted-content-length" SHOULD be present for V1 format objects.
|
||||
|| !isset($envelope[MetadataEnvelope::UNENCRYPTED_CONTENT_LENGTH_HEADER])
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function isV3Envelope(MetadataEnvelope $envelope): bool
|
||||
{
|
||||
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
|
||||
//= type=implication
|
||||
//# - The mapkey "x-amz-3" MUST be present for V3 format objects.
|
||||
if (!isset($envelope[MetadataEnvelope::ENCRYPTED_DATA_KEY_V3])
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
|
||||
//= type=implication
|
||||
//# - The mapkey "x-amz-c" MUST be present for V3 format objects.
|
||||
|| !isset($envelope[MetadataEnvelope::CONTENT_CIPHER_V3])
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
|
||||
//= type=implication
|
||||
//# - The mapkey "x-amz-d" MUST be present for V3 format objects.
|
||||
|| !isset($envelope[MetadataEnvelope::KEY_COMMITMENT_V3])
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
|
||||
//= type=implication
|
||||
//# - The mapkey "x-amz-i" MUST be present for V3 format objects.
|
||||
|| !isset($envelope[MetadataEnvelope::MESSAGE_ID_V3])
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
|
||||
//= type=implication
|
||||
//# - The mapkey "x-amz-w" MUST be present for V3 format objects.
|
||||
|| !isset($envelope[MetadataEnvelope::ENCRYPTED_DATA_KEY_ALGORITHM_V3])
|
||||
//= ../specification/s3-encryption/data-format/content-metadata.md#content-metadata-mapkeys
|
||||
//= type=implication
|
||||
//# - The mapkey "x-amz-t" SHOULD be present for V3 format objects that use KMS Encryption Context.
|
||||
|| !isset($envelope[MetadataEnvelope::ENCRYPTION_CONTEXT_V3])
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function getV2Fields(): array
|
||||
{
|
||||
return [
|
||||
MetadataEnvelope::CONTENT_KEY_V2_HEADER,
|
||||
MetadataEnvelope::MATERIALS_DESCRIPTION_HEADER,
|
||||
MetadataEnvelope::IV_HEADER,
|
||||
MetadataEnvelope::KEY_WRAP_ALGORITHM_HEADER,
|
||||
MetadataEnvelope::CONTENT_CRYPTO_SCHEME_HEADER,
|
||||
MetadataEnvelope::CRYPTO_TAG_LENGTH_HEADER
|
||||
];
|
||||
}
|
||||
|
||||
public static function getV3Fields(): array
|
||||
{
|
||||
return [
|
||||
MetadataEnvelope::ENCRYPTED_DATA_KEY_V3,
|
||||
MetadataEnvelope::CONTENT_CIPHER_V3,
|
||||
MetadataEnvelope::KEY_COMMITMENT_V3,
|
||||
MetadataEnvelope::MESSAGE_ID_V3,
|
||||
MetadataEnvelope::ENCRYPTED_DATA_KEY_ALGORITHM_V3,
|
||||
MetadataEnvelope::ENCRYPTION_CONTEXT_V3
|
||||
];
|
||||
}
|
||||
}
|
||||
30
vendor/aws/aws-sdk-php/src/Crypto/MetadataStrategyInterface.php
vendored
Normal file
30
vendor/aws/aws-sdk-php/src/Crypto/MetadataStrategyInterface.php
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
namespace Aws\Crypto;
|
||||
|
||||
interface MetadataStrategyInterface
|
||||
{
|
||||
/**
|
||||
* Places the information in the MetadataEnvelope to the strategy specific
|
||||
* location. Populates the PutObject arguments with any information
|
||||
* necessary for loading.
|
||||
*
|
||||
* @param MetadataEnvelope $envelope Encryption data to save according to
|
||||
* the strategy.
|
||||
* @param array $args Starting arguments for PutObject.
|
||||
*
|
||||
* @return array Updated arguments for PutObject.
|
||||
*/
|
||||
public function save(MetadataEnvelope $envelope, array $args);
|
||||
|
||||
/**
|
||||
* Generates a MetadataEnvelope according to the specific strategy using the
|
||||
* passed arguments.
|
||||
*
|
||||
* @param array $args Arguments from Command and Result that contains
|
||||
* S3 Object information, relevant headers, and command
|
||||
* configuration.
|
||||
*
|
||||
* @return MetadataEnvelope
|
||||
*/
|
||||
public function load(array $args);
|
||||
}
|
||||
Reference in New Issue
Block a user