File: /home4/cca63905/public_html/nueva/modules/wnetsecurity/src/JWT/RsaKeysProvider.php
<?php
/**
* Copyright since 2014 Waynet Sp. z o.o.
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to kontakt@waynet.pl so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop-project.org/ for more information.
*
* @author Waynet Sp. z o.o. <kontakt@waynet.pl>
* @copyright since 2014 Waynet Sp. z o.o.
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace Waynet\Security\JWT;
use Lcobucci\JWT\Parsing\Encoder;
use Lcobucci\JWT\Signer;
use Lcobucci\JWT\Signer\Key\InMemory;
use Lcobucci\JWT\Signer\Rsa\Sha256;
use phpseclib\Crypt\RSA;
use phpseclib\Math\BigInteger;
use Waynet\OAuth2\Client\JWT\SignerProviderInterface;
use Waynet\Security\Exception\UnableToDecryptDataException;
use Waynet\Security\Repository\Configuration\RsaKeysRepository;
class RsaKeysProvider implements JsonWebKeyProviderInterface, SignerProviderInterface
{
private $repository;
private $encoder;
private $signer;
private $rsa;
private $keyLoaded = false;
public function __construct(RsaKeysRepository $repository)
{
$this->repository = $repository;
$this->encoder = new Encoder();
$this->signer = new Sha256();
$this->rsa = new RSA();
$this->rsa->setHash('sha256');
}
public function getKeyId(): string
{
return 'rsa_sig';
}
public function getJsonWebKey(): ?array
{
try {
['n' => $modulus, 'e' => $exponent] = $this->getRawPublicKey();
} catch (\Exception $exception) {
return null;
}
return [
'kty' => 'RSA',
'alg' => $this->getSigner()->getAlgorithmId(),
'use' => 'sig',
'n' => $this->encoder->base64UrlEncode($modulus->toBytes()),
'e' => $this->encoder->base64UrlEncode($exponent->toBytes()),
'kid' => $this->getKeyId(),
];
}
public function getSigner(): Signer
{
return $this->signer;
}
public function getKey(): Signer\Key
{
return InMemory::plainText($this->getPemPrivateKey());
}
private function generateKeys(): void
{
$this->rsa->setPrivateKeyFormat(RSA::PRIVATE_FORMAT_PKCS1);
$this->rsa->setPublicKeyFormat(RSA::PUBLIC_FORMAT_PKCS1);
$partialKey = [];
do {
[
'privatekey' => $privateKey,
'publickey' => $publicKey,
'partialkey' => $partialKey
] = $this->rsa->createKey(2048, false, $partialKey);
} while (!empty($partialKey));
$this->repository->updateKeys($privateKey, $publicKey);
if (!$this->rsa->loadKey($privateKey, RSA::PRIVATE_FORMAT_PKCS1)) {
throw new \RuntimeException('Private key is malformed');
}
$this->keyLoaded = true;
}
public function getPemPublicKey(): string
{
return $this->getPublicKey(RSA::PUBLIC_FORMAT_PKCS1);
}
/**
* @return array{n: BigInteger, e: BigInteger}
*/
private function getRawPublicKey(): array
{
return $this->getPublicKey(RSA::PUBLIC_FORMAT_RAW);
}
private function getPemPrivateKey(): string
{
return $this->getPrivateKey(RSA::PRIVATE_FORMAT_PKCS1);
}
/** @return BigInteger[]|string */
private function getPublicKey(int $format)
{
$this->loadKey();
if (RSA::PUBLIC_FORMAT_PKCS1 === $format) {
return $this->repository->getPublicKey();
}
return $this->rsa->getPublicKey($format);
}
private function getPrivateKey(int $format)
{
$this->loadKey();
if (RSA::PRIVATE_FORMAT_PKCS1 === $format) {
return $this->repository->getPrivateKey();
}
return $this->rsa->getPrivateKey($format);
}
private function loadKey(): void
{
if ($this->keyLoaded) {
return;
}
try {
$privateKey = $this->repository->getPrivateKey();
} catch (UnableToDecryptDataException $exception) {
// secret changed, key must be regenerated
$privateKey = null;
}
if (
null !== $privateKey
&& $this->rsa->loadKey($privateKey, RSA::PRIVATE_FORMAT_PKCS1)
) {
$this->keyLoaded = true;
} else {
$this->generateKeys();
}
}
}