updated-packages

This commit is contained in:
RafficMohammed
2023-01-08 00:13:22 +05:30
parent 3ff7df7487
commit da241bacb6
12659 changed files with 563377 additions and 510538 deletions

View File

@@ -7,10 +7,10 @@
namespace Lcobucci\JWT;
use BadMethodCallException;
use Lcobucci\JWT\Claim\Factory as ClaimFactory;
use Lcobucci\JWT\Parsing\Encoder;
use Lcobucci\JWT\Signer\Key;
use function implode;
/**
* This class makes easier the token creation process
@@ -25,21 +25,14 @@ class Builder
*
* @var array
*/
private $headers;
private $headers = ['typ'=> 'JWT', 'alg' => 'none'];
/**
* The token claim set
*
* @var array
*/
private $claims;
/**
* The token signature
*
* @var Signature
*/
private $signature;
private $claims = [];
/**
* The data encoder
@@ -55,6 +48,16 @@ class Builder
*/
private $claimFactory;
/**
* @var Signer|null
*/
private $signer;
/**
* @var Key|null
*/
private $key;
/**
* Initializes a new builder
*
@@ -67,13 +70,43 @@ class Builder
) {
$this->encoder = $encoder ?: new Encoder();
$this->claimFactory = $claimFactory ?: new ClaimFactory();
$this->headers = ['typ'=> 'JWT', 'alg' => 'none'];
$this->claims = [];
}
/**
* Configures the audience
*
* @deprecated This method has been wrongly added and doesn't exist on v4
* @see Builder::permittedFor()
*
* @param string $audience
* @param bool $replicateAsHeader
*
* @return Builder
*/
public function canOnlyBeUsedBy($audience, $replicateAsHeader = false)
{
return $this->setRegisteredClaim('aud', (string) $audience, $replicateAsHeader);
}
/**
* Configures the audience
*
* @param string $audience
* @param bool $replicateAsHeader
*
* @return Builder
*/
public function permittedFor($audience, $replicateAsHeader = false)
{
return $this->setRegisteredClaim('aud', (string) $audience, $replicateAsHeader);
}
/**
* Configures the audience
*
* @deprecated This method will be removed on v4
* @see Builder::permittedFor()
*
* @param string $audience
* @param boolean $replicateAsHeader
*
@@ -92,6 +125,22 @@ class Builder
*
* @return Builder
*/
public function expiresAt($expiration, $replicateAsHeader = false)
{
return $this->setRegisteredClaim('exp', (int) $expiration, $replicateAsHeader);
}
/**
* Configures the expiration time
*
* @deprecated This method will be removed on v4
* @see Builder::expiresAt()
*
* @param int $expiration
* @param boolean $replicateAsHeader
*
* @return Builder
*/
public function setExpiration($expiration, $replicateAsHeader = false)
{
return $this->setRegisteredClaim('exp', (int) $expiration, $replicateAsHeader);
@@ -105,11 +154,27 @@ class Builder
*
* @return Builder
*/
public function setId($id, $replicateAsHeader = false)
public function identifiedBy($id, $replicateAsHeader = false)
{
return $this->setRegisteredClaim('jti', (string) $id, $replicateAsHeader);
}
/**
* Configures the token id
*
* @deprecated This method will be removed on v4
* @see Builder::identifiedBy()
*
* @param string $id
* @param boolean $replicateAsHeader
*
* @return Builder
*/
public function setId($id, $replicateAsHeader = false)
{
return $this->identifiedBy($id, $replicateAsHeader);
}
/**
* Configures the time that the token was issued
*
@@ -118,11 +183,27 @@ class Builder
*
* @return Builder
*/
public function setIssuedAt($issuedAt, $replicateAsHeader = false)
public function issuedAt($issuedAt, $replicateAsHeader = false)
{
return $this->setRegisteredClaim('iat', (int) $issuedAt, $replicateAsHeader);
}
/**
* Configures the time that the token was issued
*
* @deprecated This method will be removed on v4
* @see Builder::issuedAt()
*
* @param int $issuedAt
* @param boolean $replicateAsHeader
*
* @return Builder
*/
public function setIssuedAt($issuedAt, $replicateAsHeader = false)
{
return $this->issuedAt($issuedAt, $replicateAsHeader);
}
/**
* Configures the issuer
*
@@ -131,11 +212,27 @@ class Builder
*
* @return Builder
*/
public function setIssuer($issuer, $replicateAsHeader = false)
public function issuedBy($issuer, $replicateAsHeader = false)
{
return $this->setRegisteredClaim('iss', (string) $issuer, $replicateAsHeader);
}
/**
* Configures the issuer
*
* @deprecated This method will be removed on v4
* @see Builder::issuedBy()
*
* @param string $issuer
* @param boolean $replicateAsHeader
*
* @return Builder
*/
public function setIssuer($issuer, $replicateAsHeader = false)
{
return $this->issuedBy($issuer, $replicateAsHeader);
}
/**
* Configures the time before which the token cannot be accepted
*
@@ -144,11 +241,27 @@ class Builder
*
* @return Builder
*/
public function setNotBefore($notBefore, $replicateAsHeader = false)
public function canOnlyBeUsedAfter($notBefore, $replicateAsHeader = false)
{
return $this->setRegisteredClaim('nbf', (int) $notBefore, $replicateAsHeader);
}
/**
* Configures the time before which the token cannot be accepted
*
* @deprecated This method will be removed on v4
* @see Builder::canOnlyBeUsedAfter()
*
* @param int $notBefore
* @param boolean $replicateAsHeader
*
* @return Builder
*/
public function setNotBefore($notBefore, $replicateAsHeader = false)
{
return $this->canOnlyBeUsedAfter($notBefore, $replicateAsHeader);
}
/**
* Configures the subject
*
@@ -157,13 +270,29 @@ class Builder
*
* @return Builder
*/
public function setSubject($subject, $replicateAsHeader = false)
public function relatedTo($subject, $replicateAsHeader = false)
{
return $this->setRegisteredClaim('sub', (string) $subject, $replicateAsHeader);
}
/**
* Configures a registed claim
* Configures the subject
*
* @deprecated This method will be removed on v4
* @see Builder::relatedTo()
*
* @param string $subject
* @param boolean $replicateAsHeader
*
* @return Builder
*/
public function setSubject($subject, $replicateAsHeader = false)
{
return $this->relatedTo($subject, $replicateAsHeader);
}
/**
* Configures a registered claim
*
* @param string $name
* @param mixed $value
@@ -173,7 +302,7 @@ class Builder
*/
protected function setRegisteredClaim($name, $value, $replicate)
{
$this->set($name, $value);
$this->withClaim($name, $value);
if ($replicate) {
$this->headers[$name] = $this->claims[$name];
@@ -189,20 +318,46 @@ class Builder
* @param mixed $value
*
* @return Builder
*
* @throws BadMethodCallException When data has been already signed
*/
public function setHeader($name, $value)
public function withHeader($name, $value)
{
if ($this->signature) {
throw new BadMethodCallException('You must unsign before make changes');
}
$this->headers[(string) $name] = $this->claimFactory->create($name, $value);
return $this;
}
/**
* Configures a header item
*
* @deprecated This method will be removed on v4
* @see Builder::withHeader()
*
* @param string $name
* @param mixed $value
*
* @return Builder
*/
public function setHeader($name, $value)
{
return $this->withHeader($name, $value);
}
/**
* Configures a claim item
*
* @deprecated This method has been wrongly added and doesn't exist on v4
* @see Builder::withClaim()
*
* @param string $name
* @param mixed $value
*
* @return Builder
*/
public function with($name, $value)
{
return $this->withClaim($name, $value);
}
/**
* Configures a claim item
*
@@ -210,23 +365,36 @@ class Builder
* @param mixed $value
*
* @return Builder
*
* @throws BadMethodCallException When data has been already signed
*/
public function set($name, $value)
public function withClaim($name, $value)
{
if ($this->signature) {
throw new BadMethodCallException('You must unsign before making changes');
}
$this->claims[(string) $name] = $this->claimFactory->create($name, $value);
return $this;
}
/**
* Configures a claim item
*
* @deprecated This method will be removed on v4
* @see Builder::withClaim()
*
* @param string $name
* @param mixed $value
*
* @return Builder
*/
public function set($name, $value)
{
return $this->withClaim($name, $value);
}
/**
* Signs the data
*
* @deprecated This method will be removed on v4
* @see Builder::getToken()
*
* @param Signer $signer
* @param Key|string $key
*
@@ -234,12 +402,12 @@ class Builder
*/
public function sign(Signer $signer, $key)
{
$signer->modifyHeader($this->headers);
if (! $key instanceof Key) {
$key = new Key($key);
}
$this->signature = $signer->sign(
$this->getToken()->getPayload(),
$key
);
$this->signer = $signer;
$this->key = $key;
return $this;
}
@@ -247,11 +415,15 @@ class Builder
/**
* Removes the signature from the builder
*
* @deprecated This method will be removed on v4
* @see Builder::getToken()
*
* @return Builder
*/
public function unsign()
{
$this->signature = null;
$this->signer = null;
$this->key = null;
return $this;
}
@@ -261,17 +433,40 @@ class Builder
*
* @return Token
*/
public function getToken()
public function getToken(Signer $signer = null, Key $key = null)
{
$signer = $signer ?: $this->signer;
$key = $key ?: $this->key;
if ($signer instanceof Signer) {
$signer->modifyHeader($this->headers);
}
$payload = [
$this->encoder->base64UrlEncode($this->encoder->jsonEncode($this->headers)),
$this->encoder->base64UrlEncode($this->encoder->jsonEncode($this->claims))
];
if ($this->signature !== null) {
$payload[] = $this->encoder->base64UrlEncode($this->signature);
$signature = $this->createSignature($payload, $signer, $key);
if ($signature !== null) {
$payload[] = $this->encoder->base64UrlEncode($signature);
}
return new Token($this->headers, $this->claims, $this->signature, $payload);
return new Token($this->headers, $this->claims, $signature, $payload);
}
/**
* @param string[] $payload
*
* @return Signature|null
*/
private function createSignature(array $payload, Signer $signer = null, Key $key = null)
{
if ($signer === null || $key === null) {
return null;
}
return $signer->sign(implode('.', $payload), $key);
}
}

View File

@@ -27,7 +27,7 @@ interface Claim extends JsonSerializable
/**
* Returns the claim value
*
* @return string
* @return mixed
*/
public function getValue();

View File

@@ -12,6 +12,8 @@ use Lcobucci\JWT\Claim;
/**
* The default claim
*
* @deprecated This class will be removed on v4
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.0.0
*/

View File

@@ -13,6 +13,8 @@ use Lcobucci\JWT\ValidationData;
/**
* Validatable claim that checks if value is strictly equals to the given data
*
* @deprecated This class will be removed on v4
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.0.0
*/

View File

@@ -12,6 +12,8 @@ use Lcobucci\JWT\Claim;
/**
* Class that create claims
*
* @deprecated This class will be removed on v4
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.0.0
*/

View File

@@ -13,6 +13,8 @@ use Lcobucci\JWT\ValidationData;
/**
* Validatable claim that checks if value is greater or equals the given data
*
* @deprecated This class will be removed on v4
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.0.0
*/

View File

@@ -13,6 +13,8 @@ use Lcobucci\JWT\ValidationData;
/**
* Validatable claim that checks if value is lesser or equals to the given data
*
* @deprecated This class will be removed on v4
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.0.0
*/

View File

@@ -12,6 +12,8 @@ use Lcobucci\JWT\ValidationData;
/**
* Basic interface for validatable token claims
*
* @deprecated This interface will be removed on v4
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.0.0
*/

View File

@@ -7,6 +7,8 @@
namespace Lcobucci\JWT;
use Lcobucci\JWT\Signer\Key;
/**
* This class represents a token signature
*
@@ -38,7 +40,7 @@ class Signature
*
* @param Signer $signer
* @param string $payload
* @param string $key
* @param Key|string $key
*
* @return boolean
*/

View File

@@ -13,6 +13,8 @@ use Lcobucci\JWT\Signer;
/**
* Base class for signers
*
* @deprecated This class will be removed on v4
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 0.1.0
*/

View File

@@ -7,13 +7,9 @@
namespace Lcobucci\JWT\Signer;
use Lcobucci\JWT\Signer\Ecdsa\KeyParser;
use Mdanter\Ecc\Crypto\Signature\Signature;
use Mdanter\Ecc\Crypto\Signature\Signer;
use Mdanter\Ecc\EccFactory;
use Mdanter\Ecc\Math\MathAdapterInterface as Adapter;
use Mdanter\Ecc\Random\RandomGeneratorFactory;
use Mdanter\Ecc\Random\RandomNumberGeneratorInterface;
use Lcobucci\JWT\Signer\Ecdsa\MultibyteStringConverter;
use Lcobucci\JWT\Signer\Ecdsa\SignatureConverter;
use const OPENSSL_KEYTYPE_EC;
/**
* Base class for ECDSA signers
@@ -21,133 +17,53 @@ use Mdanter\Ecc\Random\RandomNumberGeneratorInterface;
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.1.0
*/
abstract class Ecdsa extends BaseSigner
abstract class Ecdsa extends OpenSSL
{
/**
* @var Adapter
* @var SignatureConverter
*/
private $adapter;
private $converter;
/**
* @var Signer
*/
private $signer;
/**
* @var KeyParser
*/
private $parser;
/**
* @param Adapter $adapter
* @param EcdsaSigner $signer
* @param KeyParser $parser
*/
public function __construct(Adapter $adapter = null, Signer $signer = null, KeyParser $parser = null)
public function __construct(SignatureConverter $converter = null)
{
$this->adapter = $adapter ?: EccFactory::getAdapter();
$this->signer = $signer ?: EccFactory::getSigner($this->adapter);
$this->parser = $parser ?: new KeyParser($this->adapter);
$this->converter = $converter ?: new MultibyteStringConverter();
}
/**
* {@inheritdoc}
*/
public function createHash(
$payload,
Key $key,
RandomNumberGeneratorInterface $generator = null
) {
$privateKey = $this->parser->getPrivateKey($key);
$generator = $generator ?: RandomGeneratorFactory::getRandomGenerator();
return $this->createSignatureHash(
$this->signer->sign(
$privateKey,
$this->createSigningHash($payload),
$generator->generate($privateKey->getPoint()->getOrder())
)
);
}
/**
* Creates a binary signature with R and S coordinates
*
* @param Signature $signature
*
* @return string
*/
private function createSignatureHash(Signature $signature)
public function createHash($payload, Key $key)
{
$length = $this->getSignatureLength();
return pack(
'H*',
sprintf(
'%s%s',
str_pad($this->adapter->decHex($signature->getR()), $length, '0', STR_PAD_LEFT),
str_pad($this->adapter->decHex($signature->getS()), $length, '0', STR_PAD_LEFT)
)
return $this->converter->fromAsn1(
parent::createHash($payload, $key),
$this->getKeyLength()
);
}
/**
* Creates a hash using the signer algorithm with given payload
*
* @param string $payload
*
* @return int|string
*/
private function createSigningHash($payload)
{
return $this->adapter->hexDec(hash($this->getAlgorithm(), $payload));
}
/**
* {@inheritdoc}
*/
public function doVerify($expected, $payload, Key $key)
{
return $this->signer->verify(
$this->parser->getPublicKey($key),
$this->extractSignature($expected),
$this->createSigningHash($payload)
return parent::doVerify(
$this->converter->toAsn1($expected, $this->getKeyLength()),
$payload,
$key
);
}
/**
* Extracts R and S values from given data
* Returns the length of each point in the signature, so that we can calculate and verify R and S points properly
*
* @param string $value
*
* @return \Mdanter\Ecc\Crypto\Signature\Signature
* @internal
*/
private function extractSignature($value)
abstract public function getKeyLength();
/**
* {@inheritdoc}
*/
final public function getKeyType()
{
$length = $this->getSignatureLength();
$value = unpack('H*', $value)[1];
return new Signature(
$this->adapter->hexDec(substr($value, 0, $length)),
$this->adapter->hexDec(substr($value, $length))
);
return OPENSSL_KEYTYPE_EC;
}
/**
* Returns the length of signature parts
*
* @internal
*
* @return int
*/
abstract public function getSignatureLength();
/**
* Returns the name of algorithm to be used to create the signing hash
*
* @internal
*
* @return string
*/
abstract public function getAlgorithm();
}

View File

@@ -1,104 +0,0 @@
<?php
/**
* This file is part of Lcobucci\JWT, a simple library to handle JWT and JWS
*
* @license http://opensource.org/licenses/BSD-3-Clause BSD-3-Clause
*/
namespace Lcobucci\JWT\Signer\Ecdsa;
use InvalidArgumentException;
use Lcobucci\JWT\Signer\Key;
use Mdanter\Ecc\Math\MathAdapterInterface;
use Mdanter\Ecc\Serializer\PrivateKey\DerPrivateKeySerializer;
use Mdanter\Ecc\Serializer\PrivateKey\PemPrivateKeySerializer;
use Mdanter\Ecc\Serializer\PrivateKey\PrivateKeySerializerInterface;
use Mdanter\Ecc\Serializer\PublicKey\DerPublicKeySerializer;
use Mdanter\Ecc\Serializer\PublicKey\PemPublicKeySerializer;
use Mdanter\Ecc\Serializer\PublicKey\PublicKeySerializerInterface;
/**
* Base class for ECDSA signers
*
* @internal
*
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 3.0.4
*/
class KeyParser
{
/**
* @var PrivateKeySerializerInterface
*/
private $privateKeySerializer;
/**
* @var PublicKeySerializerInterface
*/
private $publicKeySerializer;
/**
* @param MathAdapterInterface $adapter
* @param PrivateKeySerializerInterface $privateKeySerializer
* @param PublicKeySerializerInterface $publicKeySerializer
*/
public function __construct(
MathAdapterInterface $adapter,
PrivateKeySerializerInterface $privateKeySerializer = null,
PublicKeySerializerInterface $publicKeySerializer = null
) {
$this->privateKeySerializer = $privateKeySerializer ?: new PemPrivateKeySerializer(new DerPrivateKeySerializer($adapter));
$this->publicKeySerializer = $publicKeySerializer ?: new PemPublicKeySerializer(new DerPublicKeySerializer($adapter));
}
/**
* Parses a public key from the given PEM content
*
* @param Key $key
*
* @return \Mdanter\Ecc\Crypto\Key\PublicKeyInterface
*/
public function getPublicKey(Key $key)
{
return $this->publicKeySerializer->parse($this->getKeyContent($key, 'PUBLIC KEY'));
}
/**
* Parses a private key from the given PEM content
*
* @param Key $key
*
* @return \Mdanter\Ecc\Crypto\Key\PrivateKeyInterface
*/
public function getPrivateKey(Key $key)
{
return $this->privateKeySerializer->parse($this->getKeyContent($key, 'EC PRIVATE KEY'));
}
/**
* Extracts the base 64 value from the PEM certificate
*
* @param Key $key
* @param string $header
*
* @return string
*
* @throws InvalidArgumentException When given key is not a ECDSA key
*/
private function getKeyContent(Key $key, $header)
{
$match = null;
preg_match(
'/[\-]{5}BEGIN ' . $header . '[\-]{5}(.*)[\-]{5}END ' . $header . '[\-]{5}/',
str_replace([PHP_EOL, "\n", "\r"], '', $key->getContent()),
$match
);
if (isset($match[1])) {
return $match[1];
}
throw new InvalidArgumentException('This is not a valid ECDSA key.');
}
}

View File

@@ -0,0 +1,134 @@
<?php
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2018 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*
* @link https://github.com/web-token/jwt-framework/blob/v1.2/src/Component/Core/Util/ECSignature.php
*/
namespace Lcobucci\JWT\Signer\Ecdsa;
use InvalidArgumentException;
use function bin2hex;
use function dechex;
use function hex2bin;
use function hexdec;
use function mb_strlen;
use function mb_substr;
use function str_pad;
use const STR_PAD_LEFT;
/**
* ECDSA signature converter using ext-mbstring
*
* @internal
*/
final class MultibyteStringConverter implements SignatureConverter
{
const ASN1_SEQUENCE = '30';
const ASN1_INTEGER = '02';
const ASN1_MAX_SINGLE_BYTE = 128;
const ASN1_LENGTH_2BYTES = '81';
const ASN1_BIG_INTEGER_LIMIT = '7f';
const ASN1_NEGATIVE_INTEGER = '00';
const BYTE_SIZE = 2;
public function toAsn1($signature, $length)
{
$signature = bin2hex($signature);
if (self::octetLength($signature) !== $length) {
throw new InvalidArgumentException('Invalid signature length.');
}
$pointR = self::preparePositiveInteger(mb_substr($signature, 0, $length, '8bit'));
$pointS = self::preparePositiveInteger(mb_substr($signature, $length, null, '8bit'));
$lengthR = self::octetLength($pointR);
$lengthS = self::octetLength($pointS);
$totalLength = $lengthR + $lengthS + self::BYTE_SIZE + self::BYTE_SIZE;
$lengthPrefix = $totalLength > self::ASN1_MAX_SINGLE_BYTE ? self::ASN1_LENGTH_2BYTES : '';
$asn1 = hex2bin(
self::ASN1_SEQUENCE
. $lengthPrefix . dechex($totalLength)
. self::ASN1_INTEGER . dechex($lengthR) . $pointR
. self::ASN1_INTEGER . dechex($lengthS) . $pointS
);
return $asn1;
}
private static function octetLength($data)
{
return (int) (mb_strlen($data, '8bit') / self::BYTE_SIZE);
}
private static function preparePositiveInteger($data)
{
if (mb_substr($data, 0, self::BYTE_SIZE, '8bit') > self::ASN1_BIG_INTEGER_LIMIT) {
return self::ASN1_NEGATIVE_INTEGER . $data;
}
while (mb_substr($data, 0, self::BYTE_SIZE, '8bit') === self::ASN1_NEGATIVE_INTEGER
&& mb_substr($data, 2, self::BYTE_SIZE, '8bit') <= self::ASN1_BIG_INTEGER_LIMIT) {
$data = mb_substr($data, 2, null, '8bit');
}
return $data;
}
public function fromAsn1($signature, $length)
{
$message = bin2hex($signature);
$position = 0;
if (self::readAsn1Content($message, $position, self::BYTE_SIZE) !== self::ASN1_SEQUENCE) {
throw new InvalidArgumentException('Invalid data. Should start with a sequence.');
}
if (self::readAsn1Content($message, $position, self::BYTE_SIZE) === self::ASN1_LENGTH_2BYTES) {
$position += self::BYTE_SIZE;
}
$pointR = self::retrievePositiveInteger(self::readAsn1Integer($message, $position));
$pointS = self::retrievePositiveInteger(self::readAsn1Integer($message, $position));
$points = hex2bin(str_pad($pointR, $length, '0', STR_PAD_LEFT) . str_pad($pointS, $length, '0', STR_PAD_LEFT));
return $points;
}
private static function readAsn1Content($message, &$position, $length)
{
$content = mb_substr($message, $position, $length, '8bit');
$position += $length;
return $content;
}
private static function readAsn1Integer($message, &$position)
{
if (self::readAsn1Content($message, $position, self::BYTE_SIZE) !== self::ASN1_INTEGER) {
throw new InvalidArgumentException('Invalid data. Should contain an integer.');
}
$length = (int) hexdec(self::readAsn1Content($message, $position, self::BYTE_SIZE));
return self::readAsn1Content($message, $position, $length * self::BYTE_SIZE);
}
private static function retrievePositiveInteger($data)
{
while (mb_substr($data, 0, self::BYTE_SIZE, '8bit') === self::ASN1_NEGATIVE_INTEGER
&& mb_substr($data, 2, self::BYTE_SIZE, '8bit') > self::ASN1_BIG_INTEGER_LIMIT) {
$data = mb_substr($data, 2, null, '8bit');
}
return $data;
}
}

View File

@@ -36,7 +36,7 @@ class Sha256 extends Ecdsa
/**
* {@inheritdoc}
*/
public function getSignatureLength()
public function getKeyLength()
{
return 64;
}

View File

@@ -36,7 +36,7 @@ class Sha384 extends Ecdsa
/**
* {@inheritdoc}
*/
public function getSignatureLength()
public function getKeyLength()
{
return 96;
}

View File

@@ -36,7 +36,7 @@ class Sha512 extends Ecdsa
/**
* {@inheritdoc}
*/
public function getSignatureLength()
public function getKeyLength()
{
return 132;
}

View File

@@ -0,0 +1,38 @@
<?php
namespace Lcobucci\JWT\Signer\Ecdsa;
/**
* Manipulates the result of a ECDSA signature (points R and S) according to the
* JWA specs.
*
* OpenSSL creates a signature using the ASN.1 format and, according the JWA specs,
* the signature for JWTs must be the concatenated values of points R and S (in
* big-endian octet order).
*
* @internal
*
* @see https://tools.ietf.org/html/rfc7518#page-9
* @see https://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One
*/
interface SignatureConverter
{
/**
* Converts the signature generated by OpenSSL into what JWA defines
*
* @param string $signature
* @param int $length
*
* @return string
*/
public function fromAsn1($signature, $length);
/**
* Converts the JWA signature into something OpenSSL understands
*
* @param string $points
* @param int $length
*
* @return string
*/
public function toAsn1($points, $length);
}

View File

@@ -70,7 +70,7 @@ final class Key
return $content;
} catch (Exception $exception) {
throw new InvalidArgumentException('You must inform a valid key file', 0, $exception);
throw new InvalidArgumentException('You must provide a valid key file', 0, $exception);
}
}

View File

@@ -0,0 +1,115 @@
<?php
namespace Lcobucci\JWT\Signer;
use InvalidArgumentException;
use Lcobucci\JWT\Signer;
use function assert;
use function is_array;
use function is_resource;
use function openssl_error_string;
use function openssl_free_key;
use function openssl_pkey_get_details;
use function openssl_pkey_get_private;
use function openssl_pkey_get_public;
use function openssl_sign;
use function openssl_verify;
abstract class OpenSSL extends BaseSigner
{
public function createHash($payload, Key $key)
{
$privateKey = $this->getPrivateKey($key->getContent(), $key->getPassphrase());
try {
$signature = '';
if (! openssl_sign($payload, $signature, $privateKey, $this->getAlgorithm())) {
throw new InvalidArgumentException(
'There was an error while creating the signature: ' . openssl_error_string()
);
}
return $signature;
} finally {
openssl_free_key($privateKey);
}
}
/**
* @param string $pem
* @param string $passphrase
*
* @return resource
*/
private function getPrivateKey($pem, $passphrase)
{
$privateKey = openssl_pkey_get_private($pem, $passphrase);
$this->validateKey($privateKey);
return $privateKey;
}
/**
* @param $expected
* @param $payload
* @param $pem
* @return bool
*/
public function doVerify($expected, $payload, Key $key)
{
$publicKey = $this->getPublicKey($key->getContent());
$result = openssl_verify($payload, $expected, $publicKey, $this->getAlgorithm());
openssl_free_key($publicKey);
return $result === 1;
}
/**
* @param string $pem
*
* @return resource
*/
private function getPublicKey($pem)
{
$publicKey = openssl_pkey_get_public($pem);
$this->validateKey($publicKey);
return $publicKey;
}
/**
* Raises an exception when the key type is not the expected type
*
* @param resource|bool $key
*
* @throws InvalidArgumentException
*/
private function validateKey($key)
{
if (! is_resource($key)) {
throw new InvalidArgumentException(
'It was not possible to parse your key, reason: ' . openssl_error_string()
);
}
$details = openssl_pkey_get_details($key);
if (! isset($details['key']) || $details['type'] !== $this->getKeyType()) {
throw new InvalidArgumentException('This key is not compatible with this signer');
}
}
/**
* Returns the type of key to be used to create/verify the signature (using OpenSSL constants)
*
* @internal
*/
abstract public function getKeyType();
/**
* Returns which algorithm to be used to create/verify the signature (using OpenSSL constants)
*
* @internal
*/
abstract public function getAlgorithm();
}

View File

@@ -7,7 +7,7 @@
namespace Lcobucci\JWT\Signer;
use InvalidArgumentException;
use const OPENSSL_KEYTYPE_RSA;
/**
* Base class for RSASSA-PKCS1 signers
@@ -15,66 +15,10 @@ use InvalidArgumentException;
* @author Luís Otávio Cobucci Oblonczyk <lcobucci@gmail.com>
* @since 2.1.0
*/
abstract class Rsa extends BaseSigner
abstract class Rsa extends OpenSSL
{
/**
* {@inheritdoc}
*/
public function createHash($payload, Key $key)
final public function getKeyType()
{
$key = openssl_get_privatekey($key->getContent(), $key->getPassphrase());
$this->validateKey($key);
$signature = '';
if (!openssl_sign($payload, $signature, $key, $this->getAlgorithm())) {
throw new InvalidArgumentException(
'There was an error while creating the signature: ' . openssl_error_string()
);
}
return $signature;
return OPENSSL_KEYTYPE_RSA;
}
/**
* {@inheritdoc}
*/
public function doVerify($expected, $payload, Key $key)
{
$key = openssl_get_publickey($key->getContent());
$this->validateKey($key);
return openssl_verify($payload, $expected, $key, $this->getAlgorithm()) === 1;
}
/**
* Validates if the given key is a valid RSA public/private key
*
* @param resource $key
*
* @throws InvalidArgumentException
*/
private function validateKey($key)
{
if ($key === false) {
throw new InvalidArgumentException(
'It was not possible to parse your key, reason: ' . openssl_error_string()
);
}
$details = openssl_pkey_get_details($key);
if (!isset($details['key']) || $details['type'] !== OPENSSL_KEYTYPE_RSA) {
throw new InvalidArgumentException('This key is not compatible with RSA signatures');
}
}
/**
* Returns the algorithm name
*
* @internal
*
* @return string
*/
abstract public function getAlgorithm();
}

View File

@@ -12,6 +12,7 @@ use DateTime;
use DateTimeInterface;
use Generator;
use Lcobucci\JWT\Claim\Validatable;
use Lcobucci\JWT\Signer\Key;
use OutOfBoundsException;
/**
@@ -182,7 +183,7 @@ class Token
* Verify if the key matches with the one that created the signature
*
* @param Signer $signer
* @param string $key
* @param Key|string $key
*
* @return boolean
*

View File

@@ -22,24 +22,31 @@ class ValidationData
*/
private $items;
/**
* The leeway (in seconds) to use when validating time claims
* @var int
*/
private $leeway;
/**
* Initializes the object
*
* @param int $currentTime
* @param int $leeway
*/
public function __construct($currentTime = null)
public function __construct($currentTime = null, $leeway = 0)
{
$currentTime = $currentTime ?: time();
$currentTime = $currentTime ?: time();
$this->leeway = (int) $leeway;
$this->items = [
'jti' => null,
'iss' => null,
'aud' => null,
'sub' => null,
'iat' => $currentTime,
'nbf' => $currentTime,
'exp' => $currentTime
'sub' => null
];
$this->setCurrentTime($currentTime);
}
/**
@@ -89,9 +96,11 @@ class ValidationData
*/
public function setCurrentTime($currentTime)
{
$this->items['iat'] = (int) $currentTime;
$this->items['nbf'] = (int) $currentTime;
$this->items['exp'] = (int) $currentTime;
$currentTime = (int) $currentTime;
$this->items['iat'] = $currentTime + $this->leeway;
$this->items['nbf'] = $currentTime + $this->leeway;
$this->items['exp'] = $currentTime - $this->leeway;
}
/**