| 
<?phpnamespace ParagonIE\CipherSweet\KeyProvider;
 
 use ParagonIE\ConstantTime\Base64UrlSafe;
 use ParagonIE\ConstantTime\Binary;
 use ParagonIE\ConstantTime\Hex;
 use ParagonIE\CipherSweet\Backend\Key\SymmetricKey;
 use ParagonIE\CipherSweet\Contract\BackendInterface;
 use ParagonIE\CipherSweet\Contract\KeyProviderInterface;
 use ParagonIE\CipherSweet\Exception\ArrayKeyException;
 use ParagonIE\CipherSweet\Exception\CryptoOperationException;
 
 /**
 * Class ArrayProvider
 * @package ParagonIE\CipherSweet\KeyProvider
 */
 class ArrayProvider implements KeyProviderInterface
 {
 const INDEX_SYMMETRIC_KEY = 'symmetric-key';
 
 /**
 * @var BackendInterface
 */
 private $backend;
 
 /**
 * @var string
 */
 private $rootSymmetricKey;
 
 /**
 * ArrayProvider constructor.
 *
 * @param BackendInterface $backend
 * @param array<string, string> $config
 *
 * @throws ArrayKeyException
 * @throws CryptoOperationException
 */
 public function __construct(BackendInterface $backend, array $config = [])
 {
 if (!isset($config[self::INDEX_SYMMETRIC_KEY])) {
 throw new ArrayKeyException(
 'Expected key "' .
 self::INDEX_SYMMETRIC_KEY .
 '" to be defined on array.'
 );
 }
 $this->backend = $backend;
 
 /** @var string $rawKey */
 $rawKey = $config[self::INDEX_SYMMETRIC_KEY];
 if (Binary::safeStrlen($rawKey) === 64) {
 $this->rootSymmetricKey = Hex::decode($rawKey);
 } elseif (Binary::safeStrlen($rawKey) === 44) {
 $this->rootSymmetricKey = Base64UrlSafe::decode($rawKey);
 } elseif (Binary::safeStrlen($rawKey) === 32) {
 $this->rootSymmetricKey = $rawKey;
 } else {
 throw new CryptoOperationException('Invalid key size');
 }
 }
 
 /**
 * Attempt to wipe memory.
 */
 public function __destruct()
 {
 if (\extension_loaded('sodium')) {
 \sodium_memzero($this->rootSymmetricKey);
 } elseif (\extension_loaded('libsodium')) {
 \Sodium\memzero($this->rootSymmetricKey);
 } else {
 // Worst-case scenario: Best-ditch effort to wipe memory
 $m = \str_repeat("\xff", (int) Binary::safeStrlen($this->rootSymmetricKey));
 $this->rootSymmetricKey ^= ($this->rootSymmetricKey ^ $m);
 unset($this->rootSymmetricKey);
 }
 }
 
 /**
 * @return BackendInterface
 */
 public function getBackend()
 {
 return $this->backend;
 }
 
 /**
 * @return SymmetricKey
 */
 public function getSymmetricKey()
 {
 return new SymmetricKey($this->backend, $this->rootSymmetricKey);
 }
 }
 
 |