summaryrefslogtreecommitdiff
path: root/vendor/aws/aws-sdk-php/src/Crypto/Polyfill
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/aws/aws-sdk-php/src/Crypto/Polyfill')
-rw-r--r--vendor/aws/aws-sdk-php/src/Crypto/Polyfill/AesGcm.php228
-rw-r--r--vendor/aws/aws-sdk-php/src/Crypto/Polyfill/ByteArray.php258
-rw-r--r--vendor/aws/aws-sdk-php/src/Crypto/Polyfill/Gmac.php223
-rw-r--r--vendor/aws/aws-sdk-php/src/Crypto/Polyfill/Key.php77
-rw-r--r--vendor/aws/aws-sdk-php/src/Crypto/Polyfill/NeedsTrait.php38
5 files changed, 824 insertions, 0 deletions
diff --git a/vendor/aws/aws-sdk-php/src/Crypto/Polyfill/AesGcm.php b/vendor/aws/aws-sdk-php/src/Crypto/Polyfill/AesGcm.php
new file mode 100644
index 0000000..baf8ae2
--- /dev/null
+++ b/vendor/aws/aws-sdk-php/src/Crypto/Polyfill/AesGcm.php
@@ -0,0 +1,228 @@
+<?php
+namespace Aws\Crypto\Polyfill;
+
+use Aws\Exception\CryptoPolyfillException;
+use InvalidArgumentException;
+use RangeException;
+
+/**
+ * Class AesGcm
+ *
+ * This provides a polyfill for AES-GCM encryption/decryption, with caveats:
+ *
+ * 1. Only 96-bit nonces are supported.
+ * 2. Only 128-bit authentication tags are supported. (i.e. non-truncated)
+ *
+ * Supports AES key sizes of 128-bit, 192-bit, and 256-bit.
+ *
+ * @package Aws\Crypto\Polyfill
+ */
+class AesGcm
+{
+ use NeedsTrait;
+
+ /** @var Key $aesKey */
+ private $aesKey;
+
+ /** @var int $keySize */
+ private $keySize;
+
+ /** @var int $blockSize */
+ protected $blockSize = 8192;
+
+ /**
+ * AesGcm constructor.
+ *
+ * @param Key $aesKey
+ * @param int $keySize
+ * @param int $blockSize
+ *
+ * @throws CryptoPolyfillException
+ * @throws InvalidArgumentException
+ * @throws RangeException
+ */
+ public function __construct(Key $aesKey, $keySize = 256, $blockSize = 8192)
+ {
+ /* Preconditions: */
+ self::needs(
+ \in_array($keySize, [128, 192, 256], true),
+ "Key size must be 128, 192, or 256 bits; {$keySize} given",
+ InvalidArgumentException::class
+ );
+ self::needs(
+ \is_int($blockSize) && $blockSize > 0 && $blockSize <= PHP_INT_MAX,
+ 'Block size must be a positive integer.',
+ RangeException::class
+ );
+ self::needs(
+ $aesKey->length() << 3 === $keySize,
+ 'Incorrect key size; expected ' . $keySize . ' bits, got ' . ($aesKey->length() << 3) . ' bits.'
+ );
+ $this->aesKey = $aesKey;
+ $this->keySize = $keySize;
+ }
+
+ /**
+ * Encryption interface for AES-GCM
+ *
+ * @param string $plaintext Message to be encrypted
+ * @param string $nonce Number to be used ONCE
+ * @param Key $key AES Key
+ * @param string $aad Additional authenticated data
+ * @param string &$tag Reference to variable to hold tag
+ * @param int $keySize Key size (bits)
+ * @param int $blockSize Block size (bytes) -- How much memory to buffer
+ * @return string
+ * @throws InvalidArgumentException
+ */
+ public static function encrypt(
+ $plaintext,
+ $nonce,
+ Key $key,
+ $aad,
+ &$tag,
+ $keySize = 256,
+ $blockSize = 8192
+ ) {
+ self::needs(
+ self::strlen($nonce) === 12,
+ 'Nonce must be exactly 12 bytes',
+ InvalidArgumentException::class
+ );
+
+ $encryptor = new AesGcm($key, $keySize, $blockSize);
+ list($aadLength, $gmac) = $encryptor->gmacInit($nonce, $aad);
+
+ $ciphertext = \openssl_encrypt(
+ $plaintext,
+ "aes-{$encryptor->keySize}-ctr",
+ $key->get(),
+ OPENSSL_NO_PADDING | OPENSSL_RAW_DATA,
+ $nonce . "\x00\x00\x00\x02"
+ );
+
+ /* Calculate auth tag in a streaming fashion to minimize memory usage: */
+ $ciphertextLength = self::strlen($ciphertext);
+ for ($i = 0; $i < $ciphertextLength; $i += $encryptor->blockSize) {
+ $cBlock = new ByteArray(self::substr($ciphertext, $i, $encryptor->blockSize));
+ $gmac->update($cBlock);
+ }
+ $tag = $gmac->finish($aadLength, $ciphertextLength)->toString();
+ return $ciphertext;
+ }
+
+ /**
+ * Decryption interface for AES-GCM
+ *
+ * @param string $ciphertext Ciphertext to decrypt
+ * @param string $nonce Number to be used ONCE
+ * @param Key $key AES key
+ * @param string $aad Additional authenticated data
+ * @param string $tag Authentication tag
+ * @param int $keySize Key size (bits)
+ * @param int $blockSize Block size (bytes) -- How much memory to buffer
+ * @return string Plaintext
+ *
+ * @throws CryptoPolyfillException
+ * @throws InvalidArgumentException
+ */
+ public static function decrypt(
+ $ciphertext,
+ $nonce,
+ Key $key,
+ $aad,
+ &$tag,
+ $keySize = 256,
+ $blockSize = 8192
+ ) {
+ /* Precondition: */
+ self::needs(
+ self::strlen($nonce) === 12,
+ 'Nonce must be exactly 12 bytes',
+ InvalidArgumentException::class
+ );
+
+ $encryptor = new AesGcm($key, $keySize, $blockSize);
+ list($aadLength, $gmac) = $encryptor->gmacInit($nonce, $aad);
+
+ /* Calculate auth tag in a streaming fashion to minimize memory usage: */
+ $ciphertextLength = self::strlen($ciphertext);
+ for ($i = 0; $i < $ciphertextLength; $i += $encryptor->blockSize) {
+ $cBlock = new ByteArray(self::substr($ciphertext, $i, $encryptor->blockSize));
+ $gmac->update($cBlock);
+ }
+
+ /* Validate auth tag in constant-time: */
+ $calc = $gmac->finish($aadLength, $ciphertextLength);
+ $expected = new ByteArray($tag);
+ self::needs($calc->equals($expected), 'Invalid authentication tag');
+
+ /* Return plaintext if auth tag check succeeded: */
+ return \openssl_decrypt(
+ $ciphertext,
+ "aes-{$encryptor->keySize}-ctr",
+ $key->get(),
+ OPENSSL_NO_PADDING | OPENSSL_RAW_DATA,
+ $nonce . "\x00\x00\x00\x02"
+ );
+ }
+
+ /**
+ * Initialize a Gmac object with the nonce and this object's key.
+ *
+ * @param string $nonce Must be exactly 12 bytes long.
+ * @param string|null $aad
+ * @return array
+ */
+ protected function gmacInit($nonce, $aad = null)
+ {
+ $gmac = new Gmac(
+ $this->aesKey,
+ $nonce . "\x00\x00\x00\x01",
+ $this->keySize
+ );
+ $aadBlock = new ByteArray($aad);
+ $aadLength = $aadBlock->count();
+ $gmac->update($aadBlock);
+ $gmac->flush();
+ return [$aadLength, $gmac];
+ }
+
+ /**
+ * Calculate the length of a string.
+ *
+ * Uses the appropriate PHP function without being brittle to
+ * mbstring.func_overload.
+ *
+ * @param string $string
+ * @return int
+ */
+ protected static function strlen($string)
+ {
+ if (\is_callable('\\mb_strlen')) {
+ return (int) \mb_strlen($string, '8bit');
+ }
+ return (int) \strlen($string);
+ }
+
+ /**
+ * Return a substring of the provided string.
+ *
+ * Uses the appropriate PHP function without being brittle to
+ * mbstring.func_overload.
+ *
+ * @param string $string
+ * @param int $offset
+ * @param int|null $length
+ * @return string
+ */
+ protected static function substr($string, $offset = 0, $length = null)
+ {
+ if (\is_callable('\\mb_substr')) {
+ return \mb_substr($string, $offset, $length, '8bit');
+ } elseif (!\is_null($length)) {
+ return \substr($string, $offset, $length);
+ }
+ return \substr($string, $offset);
+ }
+}
diff --git a/vendor/aws/aws-sdk-php/src/Crypto/Polyfill/ByteArray.php b/vendor/aws/aws-sdk-php/src/Crypto/Polyfill/ByteArray.php
new file mode 100644
index 0000000..c3472b0
--- /dev/null
+++ b/vendor/aws/aws-sdk-php/src/Crypto/Polyfill/ByteArray.php
@@ -0,0 +1,258 @@
+<?php
+namespace Aws\Crypto\Polyfill;
+
+/**
+ * Class ByteArray
+ * @package Aws\Crypto\Polyfill
+ */
+class ByteArray extends \SplFixedArray
+{
+ use NeedsTrait;
+
+ /**
+ * ByteArray constructor.
+ *
+ * @param int|string|int[] $size
+ * If you pass in an integer, it creates a ByteArray of that size.
+ * If you pass in a string or array, it converts it to an array of
+ * integers between 0 and 255.
+ * @throws \InvalidArgumentException
+ */
+ public function __construct($size = 0)
+ {
+ $arr = null;
+ // Integer? This behaves just like SplFixedArray.
+ if (\is_array($size)) {
+ // Array? We need to pass the count to parent::__construct() then populate
+ $arr = $size;
+ $size = \count($arr);
+ } elseif (\is_string($size)) {
+ // We need to avoid mbstring.func_overload
+ if (\is_callable('\\mb_str_split')) {
+ $tmp = \mb_str_split($size, 1, '8bit');
+ } else {
+ $tmp = \str_split($size, 1);
+ }
+ // Let's convert each character to an 8-bit integer and store in $arr
+ $arr = [];
+ if (!empty($tmp)) {
+ foreach ($tmp as $t) {
+ if (strlen($t) < 1) {
+ continue;
+ }
+ $arr []= \unpack('C', $t)[1] & 0xff;
+ }
+ }
+ $size = \count($arr);
+ } elseif ($size instanceof ByteArray) {
+ $arr = $size->toArray();
+ $size = $size->count();
+ } elseif (!\is_int($size)) {
+ throw new \InvalidArgumentException(
+ 'Argument must be an integer, string, or array of integers.'
+ );
+ }
+
+ parent::__construct($size);
+
+ if (!empty($arr)) {
+ // Populate this object with values from constructor argument
+ foreach ($arr as $i => $v) {
+ $this->offsetSet($i, $v);
+ }
+ } else {
+ // Initialize to zero.
+ for ($i = 0; $i < $size; ++$i) {
+ $this->offsetSet($i, 0);
+ }
+ }
+ }
+
+ /**
+ * Encode an integer into a byte array. 32-bit (unsigned), big endian byte order.
+ *
+ * @param int $num
+ * @return self
+ */
+ public static function enc32be($num)
+ {
+ return new ByteArray(\pack('N', $num));
+ }
+
+ /**
+ * @param ByteArray $other
+ * @return bool
+ */
+ public function equals(ByteArray $other)
+ {
+ if ($this->count() !== $other->count()) {
+ return false;
+ }
+ $d = 0;
+ for ($i = $this->count() - 1; $i >= 0; --$i) {
+ $d |= $this[$i] ^ $other[$i];
+ }
+ return $d === 0;
+ }
+
+ /**
+ * @param ByteArray $array
+ * @return ByteArray
+ */
+ public function exclusiveOr(ByteArray $array)
+ {
+ self::needs(
+ $this->count() === $array->count(),
+ 'Both ByteArrays must be equal size for exclusiveOr()'
+ );
+ $out = clone $this;
+ for ($i = 0; $i < $this->count(); ++$i) {
+ $out[$i] = $array[$i] ^ $out[$i];
+ }
+ return $out;
+ }
+
+ /**
+ * Returns a new ByteArray incremented by 1 (big endian byte order).
+ *
+ * @param int $increase
+ * @return self
+ */
+ public function getIncremented($increase = 1)
+ {
+ $clone = clone $this;
+ $index = $clone->count();
+ while ($index > 0) {
+ --$index;
+ $tmp = ($clone[$index] + $increase) & PHP_INT_MAX;
+ $clone[$index] = $tmp & 0xff;
+ $increase = $tmp >> 8;
+ }
+ return $clone;
+ }
+
+ /**
+ * Sets a value. See SplFixedArray for more.
+ *
+ * @param int $index
+ * @param int $newval
+ * @return void
+ */
+ public function offsetSet($index, $newval)
+ {
+ parent::offsetSet($index, $newval & 0xff);
+ }
+
+ /**
+ * Return a copy of this ByteArray, bitshifted to the right by 1.
+ * Used in Gmac.
+ *
+ * @return self
+ */
+ public function rshift()
+ {
+ $out = clone $this;
+ for ($j = $this->count() - 1; $j > 0; --$j) {
+ $out[$j] = (($out[$j - 1] & 1) << 7) | ($out[$j] >> 1);
+ }
+ $out[0] >>= 1;
+ return $out;
+ }
+
+ /**
+ * Constant-time conditional select. This is meant to read like a ternary operator.
+ *
+ * $z = ByteArray::select(1, $x, $y); // $z is equal to $x
+ * $z = ByteArray::select(0, $x, $y); // $z is equal to $y
+ *
+ * @param int $select
+ * @param ByteArray $left
+ * @param ByteArray $right
+ * @return ByteArray
+ */
+ public static function select($select, ByteArray $left, ByteArray $right)
+ {
+ self::needs(
+ $left->count() === $right->count(),
+ 'Both ByteArrays must be equal size for select()'
+ );
+ $rightLength = $right->count();
+ $out = clone $right;
+ $mask = (-($select & 1)) & 0xff;
+ for ($i = 0; $i < $rightLength; $i++) {
+ $out[$i] = $out[$i] ^ (($left[$i] ^ $right[$i]) & $mask);
+ }
+ return $out;
+ }
+
+ /**
+ * Overwrite values of this ByteArray based on a separate ByteArray, with
+ * a given starting offset and length.
+ *
+ * See JavaScript's Uint8Array.set() for more information.
+ *
+ * @param ByteArray $input
+ * @param int $offset
+ * @param int|null $length
+ * @return self
+ */
+ public function set(ByteArray $input, $offset = 0, $length = null)
+ {
+ self::needs(
+ is_int($offset) && $offset >= 0,
+ 'Offset must be a positive integer or zero'
+ );
+ if (is_null($length)) {
+ $length = $input->count();
+ }
+
+ $i = 0; $j = $offset;
+ while ($i < $length && $j < $this->count()) {
+ $this[$j] = $input[$i];
+ ++$i;
+ ++$j;
+ }
+ return $this;
+ }
+
+ /**
+ * Returns a slice of this ByteArray.
+ *
+ * @param int $start
+ * @param null $length
+ * @return self
+ */
+ public function slice($start = 0, $length = null)
+ {
+ return new ByteArray(\array_slice($this->toArray(), $start, $length));
+ }
+
+ /**
+ * Mutates the current state and sets all values to zero.
+ *
+ * @return void
+ */
+ public function zeroize()
+ {
+ for ($i = $this->count() - 1; $i >= 0; --$i) {
+ $this->offsetSet($i, 0);
+ }
+ }
+
+ /**
+ * Converts the ByteArray to a raw binary string.
+ *
+ * @return string
+ */
+ public function toString()
+ {
+ $count = $this->count();
+ if ($count === 0) {
+ return '';
+ }
+ $args = $this->toArray();
+ \array_unshift($args, \str_repeat('C', $count));
+ // constant-time, PHP <5.6 equivalent to pack('C*', ...$args);
+ return \call_user_func_array('\\pack', $args);
+ }
+}
diff --git a/vendor/aws/aws-sdk-php/src/Crypto/Polyfill/Gmac.php b/vendor/aws/aws-sdk-php/src/Crypto/Polyfill/Gmac.php
new file mode 100644
index 0000000..535cfca
--- /dev/null
+++ b/vendor/aws/aws-sdk-php/src/Crypto/Polyfill/Gmac.php
@@ -0,0 +1,223 @@
+<?php
+namespace Aws\Crypto\Polyfill;
+
+/**
+ * Class Gmac
+ *
+ * @package Aws\Crypto\Polyfill
+ */
+class Gmac
+{
+ use NeedsTrait;
+
+ const BLOCK_SIZE = 16;
+
+ /** @var ByteArray $buf */
+ protected $buf;
+
+ /** @var int $bufLength */
+ protected $bufLength = 0;
+
+ /** @var ByteArray $h */
+ protected $h;
+
+ /** @var ByteArray $hf */
+ protected $hf;
+
+ /** @var Key $key */
+ protected $key;
+
+ /** @var ByteArray $x */
+ protected $x;
+
+ /**
+ * Gmac constructor.
+ *
+ * @param Key $aesKey
+ * @param string $nonce
+ * @param int $keySize
+ */
+ public function __construct(Key $aesKey, $nonce, $keySize = 256)
+ {
+ $this->buf = new ByteArray(16);
+ $this->h = new ByteArray(
+ \openssl_encrypt(
+ \str_repeat("\0", 16),
+ "aes-{$keySize}-ecb",
+ $aesKey->get(),
+ OPENSSL_RAW_DATA | OPENSSL_NO_PADDING
+ )
+ );
+ $this->key = $aesKey;
+ $this->x = new ByteArray(16);
+ $this->hf = new ByteArray(
+ \openssl_encrypt(
+ $nonce,
+ "aes-{$keySize}-ecb",
+ $aesKey->get(),
+ OPENSSL_RAW_DATA | OPENSSL_NO_PADDING
+ )
+ );
+ }
+
+ /**
+ * Update the object with some data.
+ *
+ * This method mutates this Gmac object.
+ *
+ * @param ByteArray $blocks
+ * @return self
+ */
+ public function update(ByteArray $blocks)
+ {
+ if (($blocks->count() + $this->bufLength) < self::BLOCK_SIZE) {
+ // Write to internal buffer until we reach enough to write.
+ $this->buf->set($blocks, $this->bufLength);
+ $this->bufLength += $blocks->count();
+ return $this;
+ }
+
+ // Process internal buffer first.
+ if ($this->bufLength > 0) {
+ // 0 <= state.buf_len < BLOCK_SIZE is an invariant
+ $tmp = new ByteArray(self::BLOCK_SIZE);
+ $tmp->set($this->buf->slice(0, $this->bufLength));
+ $remainingBlockLength = self::BLOCK_SIZE - $this->bufLength;
+ $tmp->set($blocks->slice(0, $remainingBlockLength), $this->bufLength);
+ $blocks = $blocks->slice($remainingBlockLength);
+ $this->bufLength = 0;
+ $this->x = $this->blockMultiply($this->x->exclusiveOr($tmp), $this->h);
+ }
+
+ // Process full blocks.
+ $numBlocks = $blocks->count() >> 4;
+ for ($i = 0; $i < $numBlocks; ++$i) {
+ $tmp = $blocks->slice($i << 4, self::BLOCK_SIZE);
+ $this->x = $this->blockMultiply($this->x->exclusiveOr($tmp), $this->h);
+ }
+ $last = $numBlocks << 4;
+
+ // Zero-fill buffer
+ for ($i = 0; $i < 16; ++$i) {
+ $this->buf[$i] = 0;
+ }
+ // Feed leftover into buffer.
+ if ($last < $blocks->count()) {
+ $tmp = $blocks->slice($last);
+ $this->buf->set($tmp);
+ $this->bufLength += ($blocks->count() - $last);
+ }
+ return $this;
+ }
+
+ /**
+ * Finish processing the authentication tag.
+ *
+ * This method mutates this Gmac object (effectively resetting it).
+ *
+ * @param int $aadLength
+ * @param int $ciphertextLength
+ * @return ByteArray
+ */
+ public function finish($aadLength, $ciphertextLength)
+ {
+ $lengthBlock = new ByteArray(16);
+ $state = $this->flush();
+
+ // AES-GCM expects bit lengths, not byte lengths.
+ $lengthBlock->set(ByteArray::enc32be($aadLength >> 29), 0);
+ $lengthBlock->set(ByteArray::enc32be($aadLength << 3), 4);
+ $lengthBlock->set(ByteArray::enc32be($ciphertextLength >> 29), 8);
+ $lengthBlock->set(ByteArray::enc32be($ciphertextLength << 3), 12);
+
+ $state->update($lengthBlock);
+ $output = $state->x->exclusiveOr($state->hf);
+
+ // Zeroize the internal values as a best-effort.
+ $state->buf->zeroize();
+ $state->x->zeroize();
+ $state->h->zeroize();
+ $state->hf->zeroize();
+ return $output;
+ }
+
+ /**
+ * Get a specific bit from the provided array, at the given index.
+ *
+ * [01234567], 8+[01234567], 16+[01234567], ...
+ *
+ * @param ByteArray $x
+ * @param int $i
+ * @return int
+ */
+ protected function bit(ByteArray $x, $i)
+ {
+ $byte = $i >> 3;
+ return ($x[$byte] >> ((7 - $i) & 7)) & 1;
+ }
+
+ /**
+ * Galois Field Multiplication
+ *
+ * This function is the critical path that must be constant-time in order to
+ * avoid timing side-channels against AES-GCM.
+ *
+ * The contents of each are always calculated, regardless of the branching
+ * condition, to prevent another kind of timing leak.
+ *
+ * @param ByteArray $x
+ * @param ByteArray $y
+ * @return ByteArray
+ */
+ protected function blockMultiply(ByteArray $x, ByteArray $y)
+ {
+ static $fieldPolynomial = null;
+ if (!$fieldPolynomial) {
+ $fieldPolynomial = new ByteArray([
+ 0xe1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ ]);
+ }
+ self::needs($x->count() === 16, 'Argument 1 must be a ByteArray of exactly 16 bytes');
+ self::needs($y->count() === 16, 'Argument 2 must be a ByteArray of exactly 16 bytes');
+
+ $v = clone $y;
+ $z = new ByteArray(16);
+
+ for ($i = 0; $i < 128; ++$i) {
+ // if ($b) $z = $z->exclusiveOr($v);
+ $b = $this->bit($x, $i);
+ $z = ByteArray::select(
+ $b,
+ $z->exclusiveOr($v),
+ $z
+ );
+
+ // if ($b) $v = $v->exclusiveOr($fieldPolynomial);
+ $b = $v[15] & 1;
+ $v = $v->rshift();
+ $v = ByteArray::select(
+ $b,
+ $v->exclusiveOr($fieldPolynomial),
+ $v
+ );
+ }
+ return $z;
+ }
+
+ /**
+ * Finish processing any leftover bytes in the internal buffer.
+ *
+ * @return self
+ */
+ public function flush()
+ {
+ if ($this->bufLength !== 0) {
+ $this->x = $this->blockMultiply(
+ $this->x->exclusiveOr($this->buf),
+ $this->h
+ );
+ $this->bufLength = 0;
+ }
+ return $this;
+ }
+}
diff --git a/vendor/aws/aws-sdk-php/src/Crypto/Polyfill/Key.php b/vendor/aws/aws-sdk-php/src/Crypto/Polyfill/Key.php
new file mode 100644
index 0000000..49d0c69
--- /dev/null
+++ b/vendor/aws/aws-sdk-php/src/Crypto/Polyfill/Key.php
@@ -0,0 +1,77 @@
+<?php
+namespace Aws\Crypto\Polyfill;
+
+/**
+ * Class Key
+ *
+ * Wraps a string to keep it hidden from stack traces.
+ *
+ * @package Aws\Crypto\Polyfill
+ */
+class Key
+{
+ /**
+ * @var string $internalString
+ */
+ private $internalString;
+
+ /**
+ * Hide contents of
+ *
+ * @return array
+ */
+ public function __debugInfo()
+ {
+ return [];
+ }
+
+ /**
+ * Key constructor.
+ * @param string $str
+ */
+ public function __construct($str)
+ {
+ $this->internalString = $str;
+ }
+
+ /**
+ * Defense in depth:
+ *
+ * PHP 7.2 includes the Sodium cryptography library, which (among other things)
+ * exposes a function called sodium_memzero() that we can use to zero-fill strings
+ * to minimize the risk of sensitive cryptographic materials persisting in memory.
+ *
+ * If this function is not available, we XOR the string in-place with itself as a
+ * best-effort attempt.
+ */
+ public function __destruct()
+ {
+ if (extension_loaded('sodium') && function_exists('sodium_memzero')) {
+ try {
+ \sodium_memzero($this->internalString);
+ } catch (\SodiumException $ex) {
+ // This is a best effort, but does not provide the same guarantees as sodium_memzero():
+ $this->internalString ^= $this->internalString;
+ }
+ }
+ }
+
+ /**
+ * @return string
+ */
+ public function get()
+ {
+ return $this->internalString;
+ }
+
+ /**
+ * @return int
+ */
+ public function length()
+ {
+ if (\is_callable('\\mb_strlen')) {
+ return (int) \mb_strlen($this->internalString, '8bit');
+ }
+ return (int) \strlen($this->internalString);
+ }
+}
diff --git a/vendor/aws/aws-sdk-php/src/Crypto/Polyfill/NeedsTrait.php b/vendor/aws/aws-sdk-php/src/Crypto/Polyfill/NeedsTrait.php
new file mode 100644
index 0000000..5ba4d64
--- /dev/null
+++ b/vendor/aws/aws-sdk-php/src/Crypto/Polyfill/NeedsTrait.php
@@ -0,0 +1,38 @@
+<?php
+namespace Aws\Crypto\Polyfill;
+
+use Aws\Exception\CryptoPolyfillException;
+
+/**
+ * Trait NeedsTrait
+ * @package Aws\Crypto\Polyfill
+ */
+trait NeedsTrait
+{
+ /**
+ * Preconditions, postconditions, and loop invariants are very
+ * useful for safe programing. They also document the specifications.
+ * This function is to help simplify the semantic burden of parsing
+ * these constructions.
+ *
+ * Instead of constructions like
+ * if (!(GOOD CONDITION)) {
+ * throw new \Exception('condition not true');
+ * }
+ *
+ * you can write:
+ * needs(GOOD CONDITION, 'condition not true');
+ * @param $condition
+ * @param $errorMessage
+ * @param null $exceptionClass
+ */
+ public static function needs($condition, $errorMessage, $exceptionClass = null)
+ {
+ if (!$condition) {
+ if (!$exceptionClass) {
+ $exceptionClass = CryptoPolyfillException::class;
+ }
+ throw new $exceptionClass($errorMessage);
+ }
+ }
+}