| 
<?phpdeclare(strict_types=1);
 namespace ParagonIE\Paserk\Types;
 
 use ParagonIE\Paserk\ConstraintTrait;
 use ParagonIE\Paserk\Operations\Wrap\Pie;
 use ParagonIE\Paserk\Operations\Wrap;
 use ParagonIE\Paserk\PaserkException;
 use ParagonIE\Paserk\PaserkTypeInterface;
 use ParagonIE\Paseto\Exception\InvalidVersionException;
 use ParagonIE\Paseto\KeyInterface;
 use ParagonIE\Paseto\Keys\{
 AsymmetricSecretKey,
 SymmetricKey
 };
 use ParagonIE\Paseto\ProtocolCollection;
 use SodiumException;
 use function array_key_exists;
 
 /**
 * Class SecretWrap
 * @package ParagonIE\Paserk\Types
 */
 class SecretWrap implements PaserkTypeInterface
 {
 use ConstraintTrait;
 
 /** @var array<string, string> */
 protected array $localCache = [];
 
 /** @var Wrap $wrap */
 protected Wrap $wrap;
 
 /**
 * SecretWrap constructor.
 * @param Wrap $wrap
 */
 public function __construct(Wrap $wrap)
 {
 $this->wrap = $wrap;
 $this->localCache = [];
 }
 
 /**
 * Quick and easy constructor-alternative for using the Pie wrapper.
 *
 * @param SymmetricKey $key
 * @return self
 *
 * @throws InvalidVersionException
 */
 public static function initWithKey(SymmetricKey $key): self
 {
 $init = new self(new Wrap(new Pie($key)));
 $init->setProtocolsAllowed(new ProtocolCollection($key->getProtocol()));
 return $init;
 }
 
 /**
 * @param string $paserk
 * @return KeyInterface
 * @throws PaserkException
 */
 public function decode(string $paserk): KeyInterface
 {
 $unwrapped = $this->wrap->secretUnwrap($paserk);
 $this->throwIfInvalidProtocol($unwrapped->getProtocol());
 /// @SPEC DETAIL: Algorithm Lucidity
 return $unwrapped;
 }
 
 /**
 * @param KeyInterface $key
 * @return string
 *
 * @throws PaserkException
 * @throws InvalidVersionException
 */
 public function encode(KeyInterface $key): string
 {
 if (!($key instanceof AsymmetricSecretKey)) {
 throw new PaserkException('Only asymmetric secret keys are allowed here');
 }
 $this->throwIfInvalidProtocol($key->getProtocol());
 /// @SPEC DETAIL: Algorithm Lucidity
 $secretId = (new SecretType($this->wrap->getProtocol()))->encode($key);
 if (!array_key_exists($secretId, $this->localCache)) {
 $this->localCache[$secretId] = $this->wrap->secretWrap($key);
 }
 return $this->localCache[$secretId];
 }
 
 /**
 * @return string
 */
 public static function getTypeLabel(): string
 {
 return 'secret-wrap';
 }
 
 /**
 * @param KeyInterface $key
 * @return string
 *
 * @throws InvalidVersionException
 * @throws PaserkException
 * @throws SodiumException
 */
 public function id(KeyInterface $key): string
 {
 return Sid::encode(
 $key->getProtocol(),
 $this->encode($key)
 );
 }
 }
 
 |