<?php
declare(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)
);
}
}
|