primo commit
This commit is contained in:
		
							
								
								
									
										12
									
								
								libraries/vendor/web-auth/metadata-service/src/CanLogData.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								libraries/vendor/web-auth/metadata-service/src/CanLogData.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService; | ||||
|  | ||||
| use Psr\Log\LoggerInterface; | ||||
|  | ||||
| interface CanLogData | ||||
| { | ||||
|     public function setLogger(LoggerInterface $logger): void; | ||||
| } | ||||
							
								
								
									
										14
									
								
								libraries/vendor/web-auth/metadata-service/src/CertificateChain/CertificateChainValidator.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								libraries/vendor/web-auth/metadata-service/src/CertificateChain/CertificateChainValidator.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\CertificateChain; | ||||
|  | ||||
| interface CertificateChainValidator | ||||
| { | ||||
|     /** | ||||
|      * @param string[] $untrustedCertificates | ||||
|      * @param string[] $trustedCertificates | ||||
|      */ | ||||
|     public function check(array $untrustedCertificates, array $trustedCertificates): void; | ||||
| } | ||||
							
								
								
									
										95
									
								
								libraries/vendor/web-auth/metadata-service/src/CertificateChain/CertificateToolbox.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								libraries/vendor/web-auth/metadata-service/src/CertificateChain/CertificateToolbox.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,95 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\CertificateChain; | ||||
|  | ||||
| use function in_array; | ||||
| use ParagonIE\ConstantTime\Base64; | ||||
| use const PHP_EOL; | ||||
| use function preg_replace; | ||||
|  | ||||
| class CertificateToolbox | ||||
| { | ||||
|     /** | ||||
|      * @param string[] $data | ||||
|      * | ||||
|      * @return string[] | ||||
|      */ | ||||
|     public static function fixPEMStructures(array $data, string $type = 'CERTIFICATE'): array | ||||
|     { | ||||
|         return array_map(static fn ($d): string => self::fixPEMStructure($d, $type), $data); | ||||
|     } | ||||
|  | ||||
|     public static function fixPEMStructure(string $data, string $type = 'CERTIFICATE'): string | ||||
|     { | ||||
|         if (str_contains($data, '-----BEGIN')) { | ||||
|             return trim($data); | ||||
|         } | ||||
|         $pem = '-----BEGIN ' . $type . '-----' . PHP_EOL; | ||||
|         $pem .= chunk_split($data, 64, PHP_EOL); | ||||
|  | ||||
|         return $pem . ('-----END ' . $type . '-----' . PHP_EOL); | ||||
|     } | ||||
|  | ||||
|     public static function convertPEMToDER(string $data): string | ||||
|     { | ||||
|         if (! str_contains($data, '-----BEGIN')) { | ||||
|             return $data; | ||||
|         } | ||||
|         $data = preg_replace('/[\-]{5}.*[\-]{5}[\r\n]*/', '', $data); | ||||
|         $data = preg_replace("/[\r\n]*/", '', $data); | ||||
|  | ||||
|         return Base64::decode(trim($data), true); | ||||
|     } | ||||
|  | ||||
|     public static function convertDERToPEM(string $data, string $type = 'CERTIFICATE'): string | ||||
|     { | ||||
|         if (str_contains($data, '-----BEGIN')) { | ||||
|             return $data; | ||||
|         } | ||||
|         $der = self::unusedBytesFix($data); | ||||
|  | ||||
|         return self::fixPEMStructure(base64_encode($der), $type); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string[] $data | ||||
|      * | ||||
|      * @return string[] | ||||
|      */ | ||||
|     public static function convertAllDERToPEM(iterable $data, string $type = 'CERTIFICATE'): array | ||||
|     { | ||||
|         $certificates = []; | ||||
|         foreach ($data as $d) { | ||||
|             $certificates[] = self::convertDERToPEM($d, $type); | ||||
|         } | ||||
|  | ||||
|         return $certificates; | ||||
|     } | ||||
|  | ||||
|     private static function unusedBytesFix(string $data): string | ||||
|     { | ||||
|         $hash = hash('sha256', $data); | ||||
|         if (in_array($hash, self::getCertificateHashes(), true)) { | ||||
|             $data[mb_strlen($data, '8bit') - 257] = "\0"; | ||||
|         } | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string[] | ||||
|      */ | ||||
|     private static function getCertificateHashes(): array | ||||
|     { | ||||
|         return [ | ||||
|             '349bca1031f8c82c4ceca38b9cebf1a69df9fb3b94eed99eb3fb9aa3822d26e8', | ||||
|             'dd574527df608e47ae45fbba75a2afdd5c20fd94a02419381813cd55a2a3398f', | ||||
|             '1d8764f0f7cd1352df6150045c8f638e517270e8b5dda1c63ade9c2280240cae', | ||||
|             'd0edc9a91a1677435a953390865d208c55b3183c6759c9b5a7ff494c322558eb', | ||||
|             '6073c436dcd064a48127ddbf6032ac1a66fd59a0c24434f070d4e564c124c897', | ||||
|             'ca993121846c464d666096d35f13bf44c1b05af205f9b4a1e00cf6cc10c5e511', | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										271
									
								
								libraries/vendor/web-auth/metadata-service/src/CertificateChain/PhpCertificateChainValidator.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										271
									
								
								libraries/vendor/web-auth/metadata-service/src/CertificateChain/PhpCertificateChainValidator.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,271 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\CertificateChain; | ||||
|  | ||||
| use function count; | ||||
| use DateTimeZone; | ||||
| use function in_array; | ||||
| use Lcobucci\Clock\Clock; | ||||
| use Lcobucci\Clock\SystemClock; | ||||
| use function parse_url; | ||||
| use const PHP_EOL; | ||||
| use const PHP_URL_SCHEME; | ||||
| use Psr\Clock\ClockInterface; | ||||
| use Psr\EventDispatcher\EventDispatcherInterface; | ||||
| use Psr\Http\Client\ClientInterface; | ||||
| use Psr\Http\Message\RequestFactoryInterface; | ||||
| use SpomkyLabs\Pki\ASN1\Type\UnspecifiedType; | ||||
| use SpomkyLabs\Pki\CryptoEncoding\PEM; | ||||
| use SpomkyLabs\Pki\X509\Certificate\Certificate; | ||||
| use SpomkyLabs\Pki\X509\CertificationPath\CertificationPath; | ||||
| use SpomkyLabs\Pki\X509\CertificationPath\PathValidation\PathValidationConfig; | ||||
| use Throwable; | ||||
| use Webauthn\MetadataService\Event\BeforeCertificateChainValidation; | ||||
| use Webauthn\MetadataService\Event\CanDispatchEvents; | ||||
| use Webauthn\MetadataService\Event\CertificateChainValidationFailed; | ||||
| use Webauthn\MetadataService\Event\CertificateChainValidationSucceeded; | ||||
| use Webauthn\MetadataService\Event\NullEventDispatcher; | ||||
| use Webauthn\MetadataService\Exception\CertificateChainException; | ||||
| use Webauthn\MetadataService\Exception\CertificateRevocationListException; | ||||
| use Webauthn\MetadataService\Exception\InvalidCertificateException; | ||||
|  | ||||
| /** | ||||
|  * @final | ||||
|  */ | ||||
| class PhpCertificateChainValidator implements CertificateChainValidator, CanDispatchEvents | ||||
| { | ||||
|     private const MAX_VALIDATION_LENGTH = 5; | ||||
|  | ||||
|     private readonly Clock|ClockInterface $clock; | ||||
|  | ||||
|     private EventDispatcherInterface $dispatcher; | ||||
|  | ||||
|     public function __construct( | ||||
|         private readonly ClientInterface $client, | ||||
|         private readonly RequestFactoryInterface $requestFactory, | ||||
|         null|Clock|ClockInterface $clock = null, | ||||
|         private readonly bool $allowFailures = true | ||||
|     ) { | ||||
|         if ($clock === null) { | ||||
|             trigger_deprecation( | ||||
|                 'web-auth/metadata-service', | ||||
|                 '4.5.0', | ||||
|                 'The parameter "$clock" will become mandatory in 5.0.0. Please set a valid PSR Clock implementation instead of "null".' | ||||
|             ); | ||||
|             $clock = new SystemClock(new DateTimeZone('UTC')); | ||||
|         } | ||||
|         $this->clock = $clock; | ||||
|         $this->dispatcher = new NullEventDispatcher(); | ||||
|     } | ||||
|  | ||||
|     public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void | ||||
|     { | ||||
|         $this->dispatcher = $eventDispatcher; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string[] $untrustedCertificates | ||||
|      * @param string[] $trustedCertificates | ||||
|      */ | ||||
|     public function check(array $untrustedCertificates, array $trustedCertificates): void | ||||
|     { | ||||
|         foreach ($trustedCertificates as $trustedCertificate) { | ||||
|             $this->dispatcher->dispatch( | ||||
|                 BeforeCertificateChainValidation::create($untrustedCertificates, $trustedCertificate) | ||||
|             ); | ||||
|             try { | ||||
|                 if ($this->validateChain($untrustedCertificates, $trustedCertificate)) { | ||||
|                     $this->dispatcher->dispatch( | ||||
|                         CertificateChainValidationSucceeded::create($untrustedCertificates, $trustedCertificate) | ||||
|                     ); | ||||
|                     return; | ||||
|                 } | ||||
|             } catch (Throwable $exception) { | ||||
|                 $this->dispatcher->dispatch( | ||||
|                     CertificateChainValidationFailed::create($untrustedCertificates, $trustedCertificate) | ||||
|                 ); | ||||
|                 throw $exception; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         throw CertificateChainException::create($untrustedCertificates, $trustedCertificates); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string[] $untrustedCertificates | ||||
|      */ | ||||
|     private function validateChain(array $untrustedCertificates, string $trustedCertificate): bool | ||||
|     { | ||||
|         $untrustedCertificates = array_map( | ||||
|             static fn (string $cert): Certificate => Certificate::fromPEM(PEM::fromString($cert)), | ||||
|             array_reverse($untrustedCertificates) | ||||
|         ); | ||||
|         $trustedCertificate = Certificate::fromPEM(PEM::fromString($trustedCertificate)); | ||||
|  | ||||
|         // The trust path and the authenticator certificate are the same | ||||
|         if (count( | ||||
|             $untrustedCertificates | ||||
|         ) === 1 && $untrustedCertificates[0]->toPEM()->string() === $trustedCertificate->toPEM()->string()) { | ||||
|             return true; | ||||
|         } | ||||
|         $uniqueCertificates = array_map( | ||||
|             static fn (Certificate $cert): string => $cert->toPEM() | ||||
|                 ->string(), | ||||
|             array_merge($untrustedCertificates, [$trustedCertificate]) | ||||
|         ); | ||||
|         count(array_unique($uniqueCertificates)) === count( | ||||
|             $uniqueCertificates | ||||
|         ) || throw CertificateChainException::create( | ||||
|             $untrustedCertificates, | ||||
|             [$trustedCertificate], | ||||
|             'Invalid certificate chain with duplicated certificates.' | ||||
|         ); | ||||
|  | ||||
|         if (! $this->validateCertificates($trustedCertificate, ...$untrustedCertificates)) { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         $certificates = array_merge([$trustedCertificate], $untrustedCertificates); | ||||
|         $numCerts = count($certificates); | ||||
|         for ($i = 1; $i < $numCerts; $i++) { | ||||
|             if ($this->isRevoked($certificates[$i])) { | ||||
|                 throw CertificateChainException::create( | ||||
|                     $untrustedCertificates, | ||||
|                     [$trustedCertificate], | ||||
|                     'Unable to validate the certificate chain. Revoked certificate found.' | ||||
|                 ); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     private function isRevoked(Certificate $subject): bool | ||||
|     { | ||||
|         try { | ||||
|             $csn = $subject->tbsCertificate() | ||||
|                 ->serialNumber(); | ||||
|         } catch (Throwable $e) { | ||||
|             throw InvalidCertificateException::create( | ||||
|                 $subject->toPEM() | ||||
|                     ->string(), | ||||
|                 sprintf('Failed to parse certificate: %s', $e->getMessage()), | ||||
|                 $e | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         try { | ||||
|             $urls = $this->getCrlUrlList($subject); | ||||
|         } catch (Throwable $e) { | ||||
|             if ($this->allowFailures) { | ||||
|                 return false; | ||||
|             } | ||||
|             throw InvalidCertificateException::create( | ||||
|                 $subject->toPEM() | ||||
|                     ->string(), | ||||
|                 'Failed to get CRL distribution points: ' . $e->getMessage(), | ||||
|                 $e | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         foreach ($urls as $url) { | ||||
|             try { | ||||
|                 $revokedCertificates = $this->retrieveRevokedSerialNumbers($url); | ||||
|  | ||||
|                 if (in_array($csn, $revokedCertificates, true)) { | ||||
|                     return true; | ||||
|                 } | ||||
|             } catch (Throwable $e) { | ||||
|                 if ($this->allowFailures) { | ||||
|                     return false; | ||||
|                 } | ||||
|                 throw CertificateRevocationListException::create($url, sprintf( | ||||
|                     'Failed to retrieve the CRL:' . PHP_EOL . '%s', | ||||
|                     $e->getMessage() | ||||
|                 ), $e); | ||||
|             } | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     private function validateCertificates(Certificate ...$certificates): bool | ||||
|     { | ||||
|         try { | ||||
|             $config = PathValidationConfig::create($this->clock->now(), self::MAX_VALIDATION_LENGTH); | ||||
|             CertificationPath::create(...$certificates)->validate($config); | ||||
|  | ||||
|             return true; | ||||
|         } catch (Throwable) { | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string[] | ||||
|      */ | ||||
|     private function retrieveRevokedSerialNumbers(string $url): array | ||||
|     { | ||||
|         try { | ||||
|             $request = $this->requestFactory->createRequest('GET', $url); | ||||
|             $response = $this->client->sendRequest($request); | ||||
|             if ($response->getStatusCode() !== 200) { | ||||
|                 throw CertificateRevocationListException::create($url, 'Failed to download the CRL'); | ||||
|             } | ||||
|             $crlData = $response->getBody() | ||||
|                 ->getContents(); | ||||
|             $crl = UnspecifiedType::fromDER($crlData)->asSequence(); | ||||
|             count($crl) === 3 || throw CertificateRevocationListException::create($url, 'Invalid CRL.'); | ||||
|             $tbsCertList = $crl->at(0) | ||||
|                 ->asSequence(); | ||||
|             count($tbsCertList) >= 6 || throw CertificateRevocationListException::create($url, 'Invalid CRL.'); | ||||
|             $list = $tbsCertList->at(5) | ||||
|                 ->asSequence(); | ||||
|  | ||||
|             return array_map(static function (UnspecifiedType $r) use ($url): string { | ||||
|                 $sequence = $r->asSequence(); | ||||
|                 count($sequence) >= 1 || throw CertificateRevocationListException::create($url, 'Invalid CRL.'); | ||||
|                 return $sequence->at(0) | ||||
|                     ->asInteger() | ||||
|                     ->number(); | ||||
|             }, $list->elements()); | ||||
|         } catch (Throwable $e) { | ||||
|             throw CertificateRevocationListException::create($url, 'Failed to download the CRL', $e); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string[] | ||||
|      */ | ||||
|     private function getCrlUrlList(Certificate $subject): array | ||||
|     { | ||||
|         try { | ||||
|             $urls = []; | ||||
|  | ||||
|             $extensions = $subject->tbsCertificate() | ||||
|                 ->extensions(); | ||||
|             if ($extensions->hasCRLDistributionPoints()) { | ||||
|                 $crlDists = $extensions->crlDistributionPoints(); | ||||
|                 foreach ($crlDists->distributionPoints() as $dist) { | ||||
|                     $url = $dist->fullName() | ||||
|                         ->names() | ||||
|                         ->firstURI(); | ||||
|                     $scheme = parse_url($url, PHP_URL_SCHEME); | ||||
|                     if (! in_array($scheme, ['http', 'https'], true)) { | ||||
|                         continue; | ||||
|                     } | ||||
|                     $urls[] = $url; | ||||
|                 } | ||||
|             } | ||||
|             return $urls; | ||||
|         } catch (Throwable $e) { | ||||
|             throw InvalidCertificateException::create( | ||||
|                 $subject->toPEM() | ||||
|                     ->string(), | ||||
|                 'Failed to get CRL distribution points from certificate: ' . $e->getMessage(), | ||||
|                 $e | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										25
									
								
								libraries/vendor/web-auth/metadata-service/src/Event/BeforeCertificateChainValidation.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								libraries/vendor/web-auth/metadata-service/src/Event/BeforeCertificateChainValidation.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Event; | ||||
|  | ||||
| final class BeforeCertificateChainValidation implements WebauthnEvent | ||||
| { | ||||
|     /** | ||||
|      * @param string[] $untrustedCertificates | ||||
|      */ | ||||
|     public function __construct( | ||||
|         public readonly array $untrustedCertificates, | ||||
|         public readonly string $trustedCertificate | ||||
|     ) { | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string[] $untrustedCertificates | ||||
|      */ | ||||
|     public static function create(array $untrustedCertificates, string $trustedCertificate): self | ||||
|     { | ||||
|         return new self($untrustedCertificates, $trustedCertificate); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										12
									
								
								libraries/vendor/web-auth/metadata-service/src/Event/CanDispatchEvents.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								libraries/vendor/web-auth/metadata-service/src/Event/CanDispatchEvents.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Event; | ||||
|  | ||||
| use Psr\EventDispatcher\EventDispatcherInterface; | ||||
|  | ||||
| interface CanDispatchEvents | ||||
| { | ||||
|     public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void; | ||||
| } | ||||
							
								
								
									
										25
									
								
								libraries/vendor/web-auth/metadata-service/src/Event/CertificateChainValidationFailed.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								libraries/vendor/web-auth/metadata-service/src/Event/CertificateChainValidationFailed.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Event; | ||||
|  | ||||
| final class CertificateChainValidationFailed implements WebauthnEvent | ||||
| { | ||||
|     /** | ||||
|      * @param string[] $untrustedCertificates | ||||
|      */ | ||||
|     public function __construct( | ||||
|         public readonly array $untrustedCertificates, | ||||
|         public readonly string $trustedCertificate | ||||
|     ) { | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string[] $untrustedCertificates | ||||
|      */ | ||||
|     public static function create(array $untrustedCertificates, string $trustedCertificate): self | ||||
|     { | ||||
|         return new self($untrustedCertificates, $trustedCertificate); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										25
									
								
								libraries/vendor/web-auth/metadata-service/src/Event/CertificateChainValidationSucceeded.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								libraries/vendor/web-auth/metadata-service/src/Event/CertificateChainValidationSucceeded.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Event; | ||||
|  | ||||
| final class CertificateChainValidationSucceeded implements WebauthnEvent | ||||
| { | ||||
|     /** | ||||
|      * @param string[] $untrustedCertificates | ||||
|      */ | ||||
|     public function __construct( | ||||
|         public readonly array $untrustedCertificates, | ||||
|         public readonly string $trustedCertificate | ||||
|     ) { | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string[] $untrustedCertificates | ||||
|      */ | ||||
|     public static function create(array $untrustedCertificates, string $trustedCertificate): self | ||||
|     { | ||||
|         return new self($untrustedCertificates, $trustedCertificate); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										20
									
								
								libraries/vendor/web-auth/metadata-service/src/Event/MetadataStatementFound.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								libraries/vendor/web-auth/metadata-service/src/Event/MetadataStatementFound.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Event; | ||||
|  | ||||
| use Webauthn\MetadataService\Statement\MetadataStatement; | ||||
|  | ||||
| final class MetadataStatementFound implements WebauthnEvent | ||||
| { | ||||
|     public function __construct( | ||||
|         public readonly MetadataStatement $metadataStatement | ||||
|     ) { | ||||
|     } | ||||
|  | ||||
|     public static function create(MetadataStatement $metadataStatement): self | ||||
|     { | ||||
|         return new self($metadataStatement); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										15
									
								
								libraries/vendor/web-auth/metadata-service/src/Event/NullEventDispatcher.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								libraries/vendor/web-auth/metadata-service/src/Event/NullEventDispatcher.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Event; | ||||
|  | ||||
| use Psr\EventDispatcher\EventDispatcherInterface; | ||||
|  | ||||
| final class NullEventDispatcher implements EventDispatcherInterface | ||||
| { | ||||
|     public function dispatch(object $event): object | ||||
|     { | ||||
|         return $event; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										9
									
								
								libraries/vendor/web-auth/metadata-service/src/Event/WebauthnEvent.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								libraries/vendor/web-auth/metadata-service/src/Event/WebauthnEvent.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Event; | ||||
|  | ||||
| interface WebauthnEvent | ||||
| { | ||||
| } | ||||
							
								
								
									
										36
									
								
								libraries/vendor/web-auth/metadata-service/src/Exception/CertificateChainException.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								libraries/vendor/web-auth/metadata-service/src/Exception/CertificateChainException.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Exception; | ||||
|  | ||||
| use Throwable; | ||||
|  | ||||
| class CertificateChainException extends MetadataServiceException | ||||
| { | ||||
|     /** | ||||
|      * @param array<string> $untrustedCertificates | ||||
|      * @param array<string> $trustedCertificates | ||||
|      */ | ||||
|     public function __construct( | ||||
|         public readonly array $untrustedCertificates, | ||||
|         public readonly array $trustedCertificates, | ||||
|         string $message, | ||||
|         ?Throwable $previous = null | ||||
|     ) { | ||||
|         parent::__construct($message, $previous); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array<string> $untrustedCertificates | ||||
|      * @param array<string> $trustedCertificates | ||||
|      */ | ||||
|     public static function create( | ||||
|         array $untrustedCertificates, | ||||
|         array $trustedCertificates, | ||||
|         string $message = 'Unable to validate the certificate chain.', | ||||
|         ?Throwable $previous = null | ||||
|     ): self { | ||||
|         return new self($untrustedCertificates, $trustedCertificates, $message, $previous); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										18
									
								
								libraries/vendor/web-auth/metadata-service/src/Exception/CertificateException.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								libraries/vendor/web-auth/metadata-service/src/Exception/CertificateException.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Exception; | ||||
|  | ||||
| use Throwable; | ||||
|  | ||||
| class CertificateException extends MetadataServiceException | ||||
| { | ||||
|     public function __construct( | ||||
|         public readonly string $certificate, | ||||
|         string $message, | ||||
|         ?Throwable $previous = null | ||||
|     ) { | ||||
|         parent::__construct($message, $previous); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										23
									
								
								libraries/vendor/web-auth/metadata-service/src/Exception/CertificateRevocationListException.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								libraries/vendor/web-auth/metadata-service/src/Exception/CertificateRevocationListException.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Exception; | ||||
|  | ||||
| use Throwable; | ||||
|  | ||||
| final class CertificateRevocationListException extends MetadataServiceException | ||||
| { | ||||
|     public function __construct( | ||||
|         public readonly string $url, | ||||
|         string $message, | ||||
|         ?Throwable $previous = null | ||||
|     ) { | ||||
|         parent::__construct($message, $previous); | ||||
|     } | ||||
|  | ||||
|     public static function create(string $url, string $message, ?Throwable $previous = null): self | ||||
|     { | ||||
|         return new self($url, $message, $previous); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										18
									
								
								libraries/vendor/web-auth/metadata-service/src/Exception/ExpiredCertificateException.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								libraries/vendor/web-auth/metadata-service/src/Exception/ExpiredCertificateException.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Exception; | ||||
|  | ||||
| use Throwable; | ||||
|  | ||||
| final class ExpiredCertificateException extends CertificateException | ||||
| { | ||||
|     public static function create( | ||||
|         string $certificate, | ||||
|         string $message = 'Expired certificate', | ||||
|         ?Throwable $previous = null | ||||
|     ): self { | ||||
|         return new self($certificate, $message, $previous); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										23
									
								
								libraries/vendor/web-auth/metadata-service/src/Exception/InvalidCertificateException.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								libraries/vendor/web-auth/metadata-service/src/Exception/InvalidCertificateException.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Exception; | ||||
|  | ||||
| use Throwable; | ||||
|  | ||||
| final class InvalidCertificateException extends MetadataServiceException | ||||
| { | ||||
|     public function __construct( | ||||
|         public readonly string $certificate, | ||||
|         string $message, | ||||
|         ?Throwable $previous = null | ||||
|     ) { | ||||
|         parent::__construct($message, $previous); | ||||
|     } | ||||
|  | ||||
|     public static function create(string $certificate, string $message, ?Throwable $previous = null): self | ||||
|     { | ||||
|         return new self($certificate, $message, $previous); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										16
									
								
								libraries/vendor/web-auth/metadata-service/src/Exception/MetadataServiceException.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								libraries/vendor/web-auth/metadata-service/src/Exception/MetadataServiceException.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Exception; | ||||
|  | ||||
| use Exception; | ||||
| use Throwable; | ||||
|  | ||||
| class MetadataServiceException extends Exception | ||||
| { | ||||
|     public function __construct(string $message, ?Throwable $previous = null) | ||||
|     { | ||||
|         parent::__construct($message, 0, $previous); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										9
									
								
								libraries/vendor/web-auth/metadata-service/src/Exception/MetadataStatementException.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								libraries/vendor/web-auth/metadata-service/src/Exception/MetadataStatementException.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Exception; | ||||
|  | ||||
| class MetadataStatementException extends MetadataServiceException | ||||
| { | ||||
| } | ||||
							
								
								
									
										15
									
								
								libraries/vendor/web-auth/metadata-service/src/Exception/MetadataStatementLoadingException.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								libraries/vendor/web-auth/metadata-service/src/Exception/MetadataStatementLoadingException.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Exception; | ||||
|  | ||||
| use Throwable; | ||||
|  | ||||
| final class MetadataStatementLoadingException extends MetadataStatementException | ||||
| { | ||||
|     public static function create(string $message, ?Throwable $previous = null): self | ||||
|     { | ||||
|         return new self($message, $previous); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										26
									
								
								libraries/vendor/web-auth/metadata-service/src/Exception/MissingMetadataStatementException.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								libraries/vendor/web-auth/metadata-service/src/Exception/MissingMetadataStatementException.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Exception; | ||||
|  | ||||
| use Throwable; | ||||
|  | ||||
| final class MissingMetadataStatementException extends MetadataStatementException | ||||
| { | ||||
|     public function __construct( | ||||
|         public readonly string $aaguid, | ||||
|         string $message, | ||||
|         ?Throwable $previous = null | ||||
|     ) { | ||||
|         parent::__construct($message, $previous); | ||||
|     } | ||||
|  | ||||
|     public static function create( | ||||
|         string $aaguid, | ||||
|         string $message = 'The Metadata Statement is missing', | ||||
|         ?Throwable $previous = null | ||||
|     ): self { | ||||
|         return new self($aaguid, $message, $previous); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										9
									
								
								libraries/vendor/web-auth/metadata-service/src/Exception/RevokedCertificateException.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								libraries/vendor/web-auth/metadata-service/src/Exception/RevokedCertificateException.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Exception; | ||||
|  | ||||
| final class RevokedCertificateException extends CertificateException | ||||
| { | ||||
| } | ||||
							
								
								
									
										12
									
								
								libraries/vendor/web-auth/metadata-service/src/MetadataStatementRepository.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								libraries/vendor/web-auth/metadata-service/src/MetadataStatementRepository.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService; | ||||
|  | ||||
| use Webauthn\MetadataService\Statement\MetadataStatement; | ||||
|  | ||||
| interface MetadataStatementRepository | ||||
| { | ||||
|     public function findOneByAAGUID(string $aaguid): ?MetadataStatement; | ||||
| } | ||||
							
								
								
									
										66
									
								
								libraries/vendor/web-auth/metadata-service/src/Service/ChainedMetadataServices.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								libraries/vendor/web-auth/metadata-service/src/Service/ChainedMetadataServices.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,66 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Service; | ||||
|  | ||||
| use Webauthn\MetadataService\Exception\MissingMetadataStatementException; | ||||
| use Webauthn\MetadataService\Statement\MetadataStatement; | ||||
|  | ||||
| final class ChainedMetadataServices implements MetadataService | ||||
| { | ||||
|     /** | ||||
|      * @var MetadataService[] | ||||
|      */ | ||||
|     private array $services = []; | ||||
|  | ||||
|     public function __construct(MetadataService ...$services) | ||||
|     { | ||||
|         foreach ($services as $service) { | ||||
|             $this->addServices($service); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static function create(MetadataService ...$services): self | ||||
|     { | ||||
|         return new self(...$services); | ||||
|     } | ||||
|  | ||||
|     public function addServices(MetadataService ...$services): self | ||||
|     { | ||||
|         foreach ($services as $service) { | ||||
|             $this->services[] = $service; | ||||
|         } | ||||
|  | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
|     public function list(): iterable | ||||
|     { | ||||
|         foreach ($this->services as $service) { | ||||
|             yield from $service->list(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public function has(string $aaguid): bool | ||||
|     { | ||||
|         foreach ($this->services as $service) { | ||||
|             if ($service->has($aaguid)) { | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     public function get(string $aaguid): MetadataStatement | ||||
|     { | ||||
|         foreach ($this->services as $service) { | ||||
|             if ($service->has($aaguid)) { | ||||
|                 return $service->get($aaguid); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         throw MissingMetadataStatementException::create($aaguid); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										130
									
								
								libraries/vendor/web-auth/metadata-service/src/Service/DistantResourceMetadataService.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										130
									
								
								libraries/vendor/web-auth/metadata-service/src/Service/DistantResourceMetadataService.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,130 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Service; | ||||
|  | ||||
| use ParagonIE\ConstantTime\Base64; | ||||
| use Psr\EventDispatcher\EventDispatcherInterface; | ||||
| use Psr\Http\Client\ClientInterface; | ||||
| use Psr\Http\Message\RequestFactoryInterface; | ||||
| use function sprintf; | ||||
| use Webauthn\MetadataService\Event\CanDispatchEvents; | ||||
| use Webauthn\MetadataService\Event\MetadataStatementFound; | ||||
| use Webauthn\MetadataService\Event\NullEventDispatcher; | ||||
| use Webauthn\MetadataService\Exception\MetadataStatementLoadingException; | ||||
| use Webauthn\MetadataService\Exception\MissingMetadataStatementException; | ||||
| use Webauthn\MetadataService\Statement\MetadataStatement; | ||||
|  | ||||
| final class DistantResourceMetadataService implements MetadataService, CanDispatchEvents | ||||
| { | ||||
|     private ?MetadataStatement $statement = null; | ||||
|  | ||||
|     private EventDispatcherInterface $dispatcher; | ||||
|  | ||||
|     /** | ||||
|      * @param array<string, string> $additionalHeaderParameters | ||||
|      */ | ||||
|     public function __construct( | ||||
|         private readonly RequestFactoryInterface $requestFactory, | ||||
|         private readonly ClientInterface $httpClient, | ||||
|         private readonly string $uri, | ||||
|         private readonly bool $isBase64Encoded = false, | ||||
|         private readonly array $additionalHeaderParameters = [], | ||||
|     ) { | ||||
|         $this->dispatcher = new NullEventDispatcher(); | ||||
|     } | ||||
|  | ||||
|     public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void | ||||
|     { | ||||
|         $this->dispatcher = $eventDispatcher; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array<string, mixed> $additionalHeaderParameters | ||||
|      */ | ||||
|     public static function create( | ||||
|         RequestFactoryInterface $requestFactory, | ||||
|         ClientInterface $httpClient, | ||||
|         string $uri, | ||||
|         bool $isBase64Encoded = false, | ||||
|         array $additionalHeaderParameters = [] | ||||
|     ): self { | ||||
|         return new self($requestFactory, $httpClient, $uri, $isBase64Encoded, $additionalHeaderParameters); | ||||
|     } | ||||
|  | ||||
|     public function list(): iterable | ||||
|     { | ||||
|         $this->loadData(); | ||||
|         $this->statement !== null || throw MetadataStatementLoadingException::create( | ||||
|             'Unable to load the metadata statement' | ||||
|         ); | ||||
|         $aaguid = $this->statement->getAaguid(); | ||||
|         if ($aaguid === null) { | ||||
|             yield from []; | ||||
|         } else { | ||||
|             yield from [$aaguid]; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public function has(string $aaguid): bool | ||||
|     { | ||||
|         $this->loadData(); | ||||
|         $this->statement !== null || throw MetadataStatementLoadingException::create( | ||||
|             'Unable to load the metadata statement' | ||||
|         ); | ||||
|  | ||||
|         return $aaguid === $this->statement->getAaguid(); | ||||
|     } | ||||
|  | ||||
|     public function get(string $aaguid): MetadataStatement | ||||
|     { | ||||
|         $this->loadData(); | ||||
|         $this->statement !== null || throw MetadataStatementLoadingException::create( | ||||
|             'Unable to load the metadata statement' | ||||
|         ); | ||||
|  | ||||
|         if ($aaguid === $this->statement->getAaguid()) { | ||||
|             $this->dispatcher->dispatch(MetadataStatementFound::create($this->statement)); | ||||
|  | ||||
|             return $this->statement; | ||||
|         } | ||||
|  | ||||
|         throw MissingMetadataStatementException::create($aaguid); | ||||
|     } | ||||
|  | ||||
|     private function loadData(): void | ||||
|     { | ||||
|         if ($this->statement !== null) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         $content = $this->fetch(); | ||||
|         if ($this->isBase64Encoded) { | ||||
|             $content = Base64::decode($content, true); | ||||
|         } | ||||
|         $this->statement = MetadataStatement::createFromString($content); | ||||
|     } | ||||
|  | ||||
|     private function fetch(): string | ||||
|     { | ||||
|         $request = $this->requestFactory->createRequest('GET', $this->uri); | ||||
|         foreach ($this->additionalHeaderParameters as $k => $v) { | ||||
|             $request = $request->withHeader($k, $v); | ||||
|         } | ||||
|         $response = $this->httpClient->sendRequest($request); | ||||
|         $response->getStatusCode() === 200 || throw MetadataStatementLoadingException::create(sprintf( | ||||
|             'Unable to contact the server. Response code is %d', | ||||
|             $response->getStatusCode() | ||||
|         )); | ||||
|         $response->getBody() | ||||
|             ->rewind(); | ||||
|         $content = $response->getBody() | ||||
|             ->getContents(); | ||||
|         $content !== '' || throw MetadataStatementLoadingException::create( | ||||
|             'Unable to contact the server. The response has no content' | ||||
|         ); | ||||
|  | ||||
|         return $content; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										226
									
								
								libraries/vendor/web-auth/metadata-service/src/Service/FidoAllianceCompliantMetadataService.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										226
									
								
								libraries/vendor/web-auth/metadata-service/src/Service/FidoAllianceCompliantMetadataService.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,226 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Service; | ||||
|  | ||||
| use function array_key_exists; | ||||
| use function is_array; | ||||
| use Jose\Component\Core\AlgorithmManager; | ||||
| use Jose\Component\KeyManagement\JWKFactory; | ||||
| use Jose\Component\Signature\Algorithm\ES256; | ||||
| use Jose\Component\Signature\Algorithm\RS256; | ||||
| use Jose\Component\Signature\JWSVerifier; | ||||
| use Jose\Component\Signature\Serializer\CompactSerializer; | ||||
| use const JSON_THROW_ON_ERROR; | ||||
| use Psr\EventDispatcher\EventDispatcherInterface; | ||||
| use Psr\Http\Client\ClientInterface; | ||||
| use Psr\Http\Message\RequestFactoryInterface; | ||||
| use function sprintf; | ||||
| use Throwable; | ||||
| use Webauthn\MetadataService\CertificateChain\CertificateChainValidator; | ||||
| use Webauthn\MetadataService\CertificateChain\CertificateToolbox; | ||||
| use Webauthn\MetadataService\Event\CanDispatchEvents; | ||||
| use Webauthn\MetadataService\Event\MetadataStatementFound; | ||||
| use Webauthn\MetadataService\Event\NullEventDispatcher; | ||||
| use Webauthn\MetadataService\Exception\MetadataStatementLoadingException; | ||||
| use Webauthn\MetadataService\Exception\MissingMetadataStatementException; | ||||
| use Webauthn\MetadataService\Statement\MetadataStatement; | ||||
| use Webauthn\MetadataService\Statement\StatusReport; | ||||
|  | ||||
| final class FidoAllianceCompliantMetadataService implements MetadataService, CanDispatchEvents | ||||
| { | ||||
|     private bool $loaded = false; | ||||
|  | ||||
|     /** | ||||
|      * @var MetadataStatement[] | ||||
|      */ | ||||
|     private array $statements = []; | ||||
|  | ||||
|     /** | ||||
|      * @var array<string, array<int, StatusReport>> | ||||
|      */ | ||||
|     private array $statusReports = []; | ||||
|  | ||||
|     private EventDispatcherInterface $dispatcher; | ||||
|  | ||||
|     /** | ||||
|      * @param array<string, mixed> $additionalHeaderParameters | ||||
|      */ | ||||
|     public function __construct( | ||||
|         private readonly RequestFactoryInterface $requestFactory, | ||||
|         private readonly ClientInterface $httpClient, | ||||
|         private readonly string $uri, | ||||
|         private readonly array $additionalHeaderParameters = [], | ||||
|         private readonly ?CertificateChainValidator $certificateChainValidator = null, | ||||
|         private readonly ?string $rootCertificateUri = null, | ||||
|     ) { | ||||
|         $this->dispatcher = new NullEventDispatcher(); | ||||
|     } | ||||
|  | ||||
|     public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void | ||||
|     { | ||||
|         $this->dispatcher = $eventDispatcher; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array<string, mixed> $additionalHeaderParameters | ||||
|      */ | ||||
|     public static function create( | ||||
|         RequestFactoryInterface $requestFactory, | ||||
|         ClientInterface $httpClient, | ||||
|         string $uri, | ||||
|         array $additionalHeaderParameters = [], | ||||
|         ?CertificateChainValidator $certificateChainValidator = null, | ||||
|         ?string $rootCertificateUri = null, | ||||
|     ): self { | ||||
|         return new self( | ||||
|             $requestFactory, | ||||
|             $httpClient, | ||||
|             $uri, | ||||
|             $additionalHeaderParameters, | ||||
|             $certificateChainValidator, | ||||
|             $rootCertificateUri | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string[] | ||||
|      */ | ||||
|     public function list(): iterable | ||||
|     { | ||||
|         $this->loadData(); | ||||
|  | ||||
|         yield from array_keys($this->statements); | ||||
|     } | ||||
|  | ||||
|     public function has(string $aaguid): bool | ||||
|     { | ||||
|         $this->loadData(); | ||||
|  | ||||
|         return array_key_exists($aaguid, $this->statements); | ||||
|     } | ||||
|  | ||||
|     public function get(string $aaguid): MetadataStatement | ||||
|     { | ||||
|         $this->loadData(); | ||||
|         array_key_exists($aaguid, $this->statements) || throw MissingMetadataStatementException::create($aaguid); | ||||
|         $mds = $this->statements[$aaguid]; | ||||
|         $this->dispatcher->dispatch(MetadataStatementFound::create($mds)); | ||||
|  | ||||
|         return $mds; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return StatusReport[] | ||||
|      */ | ||||
|     public function getStatusReports(string $aaguid): iterable | ||||
|     { | ||||
|         $this->loadData(); | ||||
|  | ||||
|         return $this->statusReports[$aaguid] ?? []; | ||||
|     } | ||||
|  | ||||
|     private function loadData(): void | ||||
|     { | ||||
|         if ($this->loaded) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         $content = $this->fetch($this->uri, $this->additionalHeaderParameters); | ||||
|         $jwtCertificates = []; | ||||
|         try { | ||||
|             $payload = $this->getJwsPayload($content, $jwtCertificates); | ||||
|             $data = json_decode($payload, true, 512, JSON_THROW_ON_ERROR); | ||||
|             $this->validateCertificates(...$jwtCertificates); | ||||
|  | ||||
|             foreach ($data['entries'] as $datum) { | ||||
|                 $entry = MetadataBLOBPayloadEntry::createFromArray($datum); | ||||
|  | ||||
|                 $mds = $entry->getMetadataStatement(); | ||||
|                 if ($mds !== null && $entry->getAaguid() !== null) { | ||||
|                     $this->statements[$entry->getAaguid()] = $mds; | ||||
|                     $this->statusReports[$entry->getAaguid()] = $entry->getStatusReports(); | ||||
|                 } | ||||
|             } | ||||
|         } catch (Throwable) { | ||||
|         } | ||||
|  | ||||
|         $this->loaded = true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array<string, mixed> $headerParameters | ||||
|      */ | ||||
|     private function fetch(string $uri, array $headerParameters): string | ||||
|     { | ||||
|         $request = $this->requestFactory->createRequest('GET', $uri); | ||||
|         foreach ($headerParameters as $k => $v) { | ||||
|             $request = $request->withHeader($k, $v); | ||||
|         } | ||||
|         $response = $this->httpClient->sendRequest($request); | ||||
|         $response->getStatusCode() === 200 || throw MetadataStatementLoadingException::create(sprintf( | ||||
|             'Unable to contact the server. Response code is %d', | ||||
|             $response->getStatusCode() | ||||
|         )); | ||||
|         $response->getBody() | ||||
|             ->rewind(); | ||||
|         $content = $response->getBody() | ||||
|             ->getContents(); | ||||
|         $content !== '' || throw MetadataStatementLoadingException::create( | ||||
|             'Unable to contact the server. The response has no content' | ||||
|         ); | ||||
|  | ||||
|         return $content; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string[] $rootCertificates | ||||
|      */ | ||||
|     private function getJwsPayload(string $token, array &$rootCertificates): string | ||||
|     { | ||||
|         $jws = (new CompactSerializer())->unserialize($token); | ||||
|         $jws->countSignatures() === 1 || throw MetadataStatementLoadingException::create( | ||||
|             'Invalid response from the metadata service. Only one signature shall be present.' | ||||
|         ); | ||||
|         $signature = $jws->getSignature(0); | ||||
|         $payload = $jws->getPayload(); | ||||
|         $payload !== '' || throw MetadataStatementLoadingException::create( | ||||
|             'Invalid response from the metadata service. The token payload is empty.' | ||||
|         ); | ||||
|         $header = $signature->getProtectedHeader(); | ||||
|         array_key_exists('alg', $header) || throw MetadataStatementLoadingException::create( | ||||
|             'The "alg" parameter is missing.' | ||||
|         ); | ||||
|         array_key_exists('x5c', $header) || throw MetadataStatementLoadingException::create( | ||||
|             'The "x5c" parameter is missing.' | ||||
|         ); | ||||
|         is_array($header['x5c']) || throw MetadataStatementLoadingException::create( | ||||
|             'The "x5c" parameter should be an array.' | ||||
|         ); | ||||
|         $key = JWKFactory::createFromX5C($header['x5c']); | ||||
|         $rootCertificates = $header['x5c']; | ||||
|  | ||||
|         $verifier = new JWSVerifier(new AlgorithmManager([new ES256(), new RS256()])); | ||||
|         $isValid = $verifier->verifyWithKey($jws, $key, 0); | ||||
|         $isValid || throw MetadataStatementLoadingException::create( | ||||
|             'Invalid response from the metadata service. The token signature is invalid.' | ||||
|         ); | ||||
|         $payload = $jws->getPayload(); | ||||
|         $payload !== null || throw MetadataStatementLoadingException::create( | ||||
|             'Invalid response from the metadata service. The payload is missing.' | ||||
|         ); | ||||
|  | ||||
|         return $payload; | ||||
|     } | ||||
|  | ||||
|     private function validateCertificates(string ...$untrustedCertificates): void | ||||
|     { | ||||
|         if ($this->certificateChainValidator === null || $this->rootCertificateUri === null) { | ||||
|             return; | ||||
|         } | ||||
|         $untrustedCertificates = CertificateToolbox::fixPEMStructures($untrustedCertificates); | ||||
|         $rootCertificate = CertificateToolbox::convertDERToPEM($this->fetch($this->rootCertificateUri, [])); | ||||
|         $this->certificateChainValidator->check($untrustedCertificates, [$rootCertificate]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										61
									
								
								libraries/vendor/web-auth/metadata-service/src/Service/FolderResourceMetadataService.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								libraries/vendor/web-auth/metadata-service/src/Service/FolderResourceMetadataService.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,61 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Service; | ||||
|  | ||||
| use const DIRECTORY_SEPARATOR; | ||||
| use function file_get_contents; | ||||
| use InvalidArgumentException; | ||||
| use function is_array; | ||||
| use RuntimeException; | ||||
| use function sprintf; | ||||
| use Webauthn\MetadataService\Statement\MetadataStatement; | ||||
|  | ||||
| final class FolderResourceMetadataService implements MetadataService | ||||
| { | ||||
|     private readonly string $rootPath; | ||||
|  | ||||
|     public function __construct(string $rootPath) | ||||
|     { | ||||
|         $this->rootPath = rtrim($rootPath, DIRECTORY_SEPARATOR); | ||||
|         is_dir($this->rootPath) || throw new InvalidArgumentException('The given parameter is not a valid folder.'); | ||||
|         is_readable($this->rootPath) || throw new InvalidArgumentException( | ||||
|             'The given parameter is not a valid folder.' | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     public function list(): iterable | ||||
|     { | ||||
|         $files = glob($this->rootPath . DIRECTORY_SEPARATOR . '*'); | ||||
|         is_array($files) || throw new RuntimeException('Unable to read files.'); | ||||
|         foreach ($files as $file) { | ||||
|             if (is_dir($file) || ! is_readable($file)) { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             yield basename($file); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public function has(string $aaguid): bool | ||||
|     { | ||||
|         $filename = $this->rootPath . DIRECTORY_SEPARATOR . $aaguid; | ||||
|  | ||||
|         return is_file($filename) && is_readable($filename); | ||||
|     } | ||||
|  | ||||
|     public function get(string $aaguid): MetadataStatement | ||||
|     { | ||||
|         $this->has($aaguid) || throw new InvalidArgumentException(sprintf( | ||||
|             'The MDS with the AAGUID "%s" does not exist.', | ||||
|             $aaguid | ||||
|         )); | ||||
|         $filename = $this->rootPath . DIRECTORY_SEPARATOR . $aaguid; | ||||
|         $data = trim(file_get_contents($filename)); | ||||
|         $mds = MetadataStatement::createFromString($data); | ||||
|         $mds->getAaguid() !== null || throw new RuntimeException('Invalid Metadata Statement.'); | ||||
|  | ||||
|         return $mds; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										73
									
								
								libraries/vendor/web-auth/metadata-service/src/Service/InMemoryMetadataService.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								libraries/vendor/web-auth/metadata-service/src/Service/InMemoryMetadataService.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,73 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Service; | ||||
|  | ||||
| use function array_key_exists; | ||||
| use Psr\EventDispatcher\EventDispatcherInterface; | ||||
| use Webauthn\MetadataService\Event\CanDispatchEvents; | ||||
| use Webauthn\MetadataService\Event\MetadataStatementFound; | ||||
| use Webauthn\MetadataService\Event\NullEventDispatcher; | ||||
| use Webauthn\MetadataService\Exception\MissingMetadataStatementException; | ||||
| use Webauthn\MetadataService\Statement\MetadataStatement; | ||||
|  | ||||
| final class InMemoryMetadataService implements MetadataService, CanDispatchEvents | ||||
| { | ||||
|     /** | ||||
|      * @var MetadataStatement[] | ||||
|      */ | ||||
|     private array $statements = []; | ||||
|  | ||||
|     private EventDispatcherInterface $dispatcher; | ||||
|  | ||||
|     public function __construct(MetadataStatement ...$statements) | ||||
|     { | ||||
|         foreach ($statements as $statement) { | ||||
|             $this->addStatements($statement); | ||||
|         } | ||||
|         $this->dispatcher = new NullEventDispatcher(); | ||||
|     } | ||||
|  | ||||
|     public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void | ||||
|     { | ||||
|         $this->dispatcher = $eventDispatcher; | ||||
|     } | ||||
|  | ||||
|     public static function create(MetadataStatement ...$statements): self | ||||
|     { | ||||
|         return new self(...$statements); | ||||
|     } | ||||
|  | ||||
|     public function addStatements(MetadataStatement ...$statements): self | ||||
|     { | ||||
|         foreach ($statements as $statement) { | ||||
|             $aaguid = $statement->getAaguid(); | ||||
|             if ($aaguid === null) { | ||||
|                 continue; | ||||
|             } | ||||
|             $this->statements[$aaguid] = $statement; | ||||
|         } | ||||
|  | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
|     public function list(): iterable | ||||
|     { | ||||
|         yield from array_keys($this->statements); | ||||
|     } | ||||
|  | ||||
|     public function has(string $aaguid): bool | ||||
|     { | ||||
|         return array_key_exists($aaguid, $this->statements); | ||||
|     } | ||||
|  | ||||
|     public function get(string $aaguid): MetadataStatement | ||||
|     { | ||||
|         array_key_exists($aaguid, $this->statements) || throw MissingMetadataStatementException::create($aaguid); | ||||
|         $mds = $this->statements[$aaguid]; | ||||
|         $this->dispatcher->dispatch(MetadataStatementFound::create($mds)); | ||||
|  | ||||
|         return $mds; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										92
									
								
								libraries/vendor/web-auth/metadata-service/src/Service/LocalResourceMetadataService.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								libraries/vendor/web-auth/metadata-service/src/Service/LocalResourceMetadataService.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,92 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Service; | ||||
|  | ||||
| use function file_get_contents; | ||||
| use ParagonIE\ConstantTime\Base64; | ||||
| use Psr\EventDispatcher\EventDispatcherInterface; | ||||
| use Webauthn\MetadataService\Event\CanDispatchEvents; | ||||
| use Webauthn\MetadataService\Event\MetadataStatementFound; | ||||
| use Webauthn\MetadataService\Event\NullEventDispatcher; | ||||
| use Webauthn\MetadataService\Exception\MetadataStatementLoadingException; | ||||
| use Webauthn\MetadataService\Exception\MissingMetadataStatementException; | ||||
| use Webauthn\MetadataService\Statement\MetadataStatement; | ||||
|  | ||||
| final class LocalResourceMetadataService implements MetadataService, CanDispatchEvents | ||||
| { | ||||
|     private ?MetadataStatement $statement = null; | ||||
|  | ||||
|     private EventDispatcherInterface $dispatcher; | ||||
|  | ||||
|     public function __construct( | ||||
|         private readonly string $filename, | ||||
|         private readonly bool $isBase64Encoded = false, | ||||
|     ) { | ||||
|         $this->dispatcher = new NullEventDispatcher(); | ||||
|     } | ||||
|  | ||||
|     public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void | ||||
|     { | ||||
|         $this->dispatcher = $eventDispatcher; | ||||
|     } | ||||
|  | ||||
|     public static function create(string $filename, bool $isBase64Encoded = false): self | ||||
|     { | ||||
|         return new self($filename, $isBase64Encoded); | ||||
|     } | ||||
|  | ||||
|     public function list(): iterable | ||||
|     { | ||||
|         $this->loadData(); | ||||
|         $this->statement !== null || throw MetadataStatementLoadingException::create( | ||||
|             'Unable to load the metadata statement' | ||||
|         ); | ||||
|         $aaguid = $this->statement->getAaguid(); | ||||
|         if ($aaguid === null) { | ||||
|             yield from []; | ||||
|         } else { | ||||
|             yield from [$aaguid]; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public function has(string $aaguid): bool | ||||
|     { | ||||
|         $this->loadData(); | ||||
|         $this->statement !== null || throw MetadataStatementLoadingException::create( | ||||
|             'Unable to load the metadata statement' | ||||
|         ); | ||||
|  | ||||
|         return $aaguid === $this->statement->getAaguid(); | ||||
|     } | ||||
|  | ||||
|     public function get(string $aaguid): MetadataStatement | ||||
|     { | ||||
|         $this->loadData(); | ||||
|         $this->statement !== null || throw MetadataStatementLoadingException::create( | ||||
|             'Unable to load the metadata statement' | ||||
|         ); | ||||
|  | ||||
|         if ($aaguid === $this->statement->getAaguid()) { | ||||
|             $this->dispatcher->dispatch(MetadataStatementFound::create($this->statement)); | ||||
|  | ||||
|             return $this->statement; | ||||
|         } | ||||
|  | ||||
|         throw MissingMetadataStatementException::create($aaguid); | ||||
|     } | ||||
|  | ||||
|     private function loadData(): void | ||||
|     { | ||||
|         if ($this->statement !== null) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         $content = file_get_contents($this->filename); | ||||
|         if ($this->isBase64Encoded) { | ||||
|             $content = Base64::decode($content, true); | ||||
|         } | ||||
|         $this->statement = MetadataStatement::createFromString($content); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										131
									
								
								libraries/vendor/web-auth/metadata-service/src/Service/MetadataBLOBPayload.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								libraries/vendor/web-auth/metadata-service/src/Service/MetadataBLOBPayload.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,131 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Service; | ||||
|  | ||||
| use function array_key_exists; | ||||
| use function is_array; | ||||
| use function is_int; | ||||
| use function is_string; | ||||
| use JsonSerializable; | ||||
| use Webauthn\MetadataService\Exception\MetadataStatementLoadingException; | ||||
| use Webauthn\MetadataService\Utils; | ||||
|  | ||||
| /** | ||||
|  * @final | ||||
|  */ | ||||
| class MetadataBLOBPayload implements JsonSerializable | ||||
| { | ||||
|     /** | ||||
|      * @var MetadataBLOBPayloadEntry[] | ||||
|      */ | ||||
|     private array $entries = []; | ||||
|  | ||||
|     /** | ||||
|      * @var string[] | ||||
|      */ | ||||
|     private array $rootCertificates = []; | ||||
|  | ||||
|     public function __construct( | ||||
|         private readonly int $no, | ||||
|         private readonly string $nextUpdate, | ||||
|         private readonly ?string $legalHeader = null | ||||
|     ) { | ||||
|     } | ||||
|  | ||||
|     public function addEntry(MetadataBLOBPayloadEntry $entry): self | ||||
|     { | ||||
|         $this->entries[] = $entry; | ||||
|  | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
|     public function getLegalHeader(): ?string | ||||
|     { | ||||
|         return $this->legalHeader; | ||||
|     } | ||||
|  | ||||
|     public function getNo(): int | ||||
|     { | ||||
|         return $this->no; | ||||
|     } | ||||
|  | ||||
|     public function getNextUpdate(): string | ||||
|     { | ||||
|         return $this->nextUpdate; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return MetadataBLOBPayloadEntry[] | ||||
|      */ | ||||
|     public function getEntries(): array | ||||
|     { | ||||
|         return $this->entries; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array<string, mixed> $data | ||||
|      */ | ||||
|     public static function createFromArray(array $data): self | ||||
|     { | ||||
|         $data = Utils::filterNullValues($data); | ||||
|         foreach (['no', 'nextUpdate', 'entries'] as $key) { | ||||
|             array_key_exists($key, $data) || throw MetadataStatementLoadingException::create(sprintf( | ||||
|                 'Invalid data. The parameter "%s" is missing', | ||||
|                 $key | ||||
|             )); | ||||
|         } | ||||
|         is_int($data['no']) || throw MetadataStatementLoadingException::create( | ||||
|             'Invalid data. The parameter "no" shall be an integer' | ||||
|         ); | ||||
|         is_string($data['nextUpdate']) || throw MetadataStatementLoadingException::create( | ||||
|             'Invalid data. The parameter "nextUpdate" shall be a string' | ||||
|         ); | ||||
|         is_array($data['entries']) || throw MetadataStatementLoadingException::create( | ||||
|             'Invalid data. The parameter "entries" shall be a n array of entries' | ||||
|         ); | ||||
|         $object = new self($data['no'], $data['nextUpdate'], $data['legalHeader'] ?? null); | ||||
|         foreach ($data['entries'] as $entry) { | ||||
|             $object->addEntry(MetadataBLOBPayloadEntry::createFromArray($entry)); | ||||
|         } | ||||
|  | ||||
|         return $object; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array<string, mixed> | ||||
|      */ | ||||
|     public function jsonSerialize(): array | ||||
|     { | ||||
|         $data = [ | ||||
|             'legalHeader' => $this->legalHeader, | ||||
|             'nextUpdate' => $this->nextUpdate, | ||||
|             'no' => $this->no, | ||||
|             'entries' => array_map( | ||||
|                 static fn (MetadataBLOBPayloadEntry $object): array => $object->jsonSerialize(), | ||||
|                 $this->entries | ||||
|             ), | ||||
|         ]; | ||||
|  | ||||
|         return Utils::filterNullValues($data); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string[] | ||||
|      */ | ||||
|     public function getRootCertificates(): array | ||||
|     { | ||||
|         return $this->rootCertificates; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string[] $rootCertificates | ||||
|      */ | ||||
|     public function setRootCertificates(array $rootCertificates): self | ||||
|     { | ||||
|         $this->rootCertificates = $rootCertificates; | ||||
|  | ||||
|         return $this; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										200
									
								
								libraries/vendor/web-auth/metadata-service/src/Service/MetadataBLOBPayloadEntry.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										200
									
								
								libraries/vendor/web-auth/metadata-service/src/Service/MetadataBLOBPayloadEntry.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,200 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Service; | ||||
|  | ||||
| use function array_key_exists; | ||||
| use function count; | ||||
| use function is_array; | ||||
| use function is_string; | ||||
| use JsonSerializable; | ||||
| use Webauthn\MetadataService\Exception\MetadataStatementLoadingException; | ||||
| use Webauthn\MetadataService\Statement\BiometricStatusReport; | ||||
| use Webauthn\MetadataService\Statement\MetadataStatement; | ||||
| use Webauthn\MetadataService\Statement\StatusReport; | ||||
| use Webauthn\MetadataService\Utils; | ||||
|  | ||||
| /** | ||||
|  * @final | ||||
|  */ | ||||
| class MetadataBLOBPayloadEntry implements JsonSerializable | ||||
| { | ||||
|     /** | ||||
|      * @var string[] | ||||
|      */ | ||||
|     private array $attestationCertificateKeyIdentifiers = []; | ||||
|  | ||||
|     /** | ||||
|      * @var BiometricStatusReport[] | ||||
|      */ | ||||
|     private array $biometricStatusReports = []; | ||||
|  | ||||
|     /** | ||||
|      * @var StatusReport[] | ||||
|      */ | ||||
|     private array $statusReports = []; | ||||
|  | ||||
|     /** | ||||
|      * @param string[] $attestationCertificateKeyIdentifiers | ||||
|      */ | ||||
|     public function __construct( | ||||
|         private readonly ?string $aaid, | ||||
|         private readonly ?string $aaguid, | ||||
|         array $attestationCertificateKeyIdentifiers, | ||||
|         private readonly ?MetadataStatement $metadataStatement, | ||||
|         private readonly string $timeOfLastStatusChange, | ||||
|         private readonly ?string $rogueListURL, | ||||
|         private readonly ?string $rogueListHash | ||||
|     ) { | ||||
|         if ($aaid !== null && $aaguid !== null) { | ||||
|             throw MetadataStatementLoadingException::create('Authenticators cannot support both AAID and AAGUID'); | ||||
|         } | ||||
|         if ($aaid === null && $aaguid === null && count($attestationCertificateKeyIdentifiers) === 0) { | ||||
|             throw MetadataStatementLoadingException::create( | ||||
|                 'If neither AAID nor AAGUID are set, the attestation certificate identifier list shall not be empty' | ||||
|             ); | ||||
|         } | ||||
|         foreach ($attestationCertificateKeyIdentifiers as $attestationCertificateKeyIdentifier) { | ||||
|             is_string($attestationCertificateKeyIdentifier) || throw MetadataStatementLoadingException::create( | ||||
|                 'Invalid attestation certificate identifier. Shall be a list of strings' | ||||
|             ); | ||||
|             preg_match( | ||||
|                 '/^[0-9a-f]+$/', | ||||
|                 $attestationCertificateKeyIdentifier | ||||
|             ) === 1 || throw MetadataStatementLoadingException::create( | ||||
|                 'Invalid attestation certificate identifier. Shall be a list of strings' | ||||
|             ); | ||||
|         } | ||||
|         $this->attestationCertificateKeyIdentifiers = $attestationCertificateKeyIdentifiers; | ||||
|     } | ||||
|  | ||||
|     public function getAaid(): ?string | ||||
|     { | ||||
|         return $this->aaid; | ||||
|     } | ||||
|  | ||||
|     public function getAaguid(): ?string | ||||
|     { | ||||
|         return $this->aaguid; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string[] | ||||
|      */ | ||||
|     public function getAttestationCertificateKeyIdentifiers(): array | ||||
|     { | ||||
|         return $this->attestationCertificateKeyIdentifiers; | ||||
|     } | ||||
|  | ||||
|     public function getMetadataStatement(): ?MetadataStatement | ||||
|     { | ||||
|         return $this->metadataStatement; | ||||
|     } | ||||
|  | ||||
|     public function addBiometricStatusReports(BiometricStatusReport ...$biometricStatusReports): self | ||||
|     { | ||||
|         foreach ($biometricStatusReports as $biometricStatusReport) { | ||||
|             $this->biometricStatusReports[] = $biometricStatusReport; | ||||
|         } | ||||
|  | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return BiometricStatusReport[] | ||||
|      */ | ||||
|     public function getBiometricStatusReports(): array | ||||
|     { | ||||
|         return $this->biometricStatusReports; | ||||
|     } | ||||
|  | ||||
|     public function addStatusReports(StatusReport ...$statusReports): self | ||||
|     { | ||||
|         foreach ($statusReports as $statusReport) { | ||||
|             $this->statusReports[] = $statusReport; | ||||
|         } | ||||
|  | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return StatusReport[] | ||||
|      */ | ||||
|     public function getStatusReports(): array | ||||
|     { | ||||
|         return $this->statusReports; | ||||
|     } | ||||
|  | ||||
|     public function getTimeOfLastStatusChange(): string | ||||
|     { | ||||
|         return $this->timeOfLastStatusChange; | ||||
|     } | ||||
|  | ||||
|     public function getRogueListURL(): string|null | ||||
|     { | ||||
|         return $this->rogueListURL; | ||||
|     } | ||||
|  | ||||
|     public function getRogueListHash(): string|null | ||||
|     { | ||||
|         return $this->rogueListHash; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array<string, mixed> $data | ||||
|      */ | ||||
|     public static function createFromArray(array $data): self | ||||
|     { | ||||
|         $data = Utils::filterNullValues($data); | ||||
|         array_key_exists('timeOfLastStatusChange', $data) || throw MetadataStatementLoadingException::create( | ||||
|             'Invalid data. The parameter "timeOfLastStatusChange" is missing' | ||||
|         ); | ||||
|         array_key_exists('statusReports', $data) || throw MetadataStatementLoadingException::create( | ||||
|             'Invalid data. The parameter "statusReports" is missing' | ||||
|         ); | ||||
|         is_array($data['statusReports']) || throw MetadataStatementLoadingException::create( | ||||
|             'Invalid data. The parameter "statusReports" shall be an array of StatusReport objects' | ||||
|         ); | ||||
|         $object = new self( | ||||
|             $data['aaid'] ?? null, | ||||
|             $data['aaguid'] ?? null, | ||||
|             $data['attestationCertificateKeyIdentifiers'] ?? [], | ||||
|             isset($data['metadataStatement']) ? MetadataStatement::createFromArray($data['metadataStatement']) : null, | ||||
|             $data['timeOfLastStatusChange'], | ||||
|             $data['rogueListURL'] ?? null, | ||||
|             $data['rogueListHash'] ?? null | ||||
|         ); | ||||
|         foreach ($data['statusReports'] as $statusReport) { | ||||
|             $object->addStatusReports(StatusReport::createFromArray($statusReport)); | ||||
|         } | ||||
|         if (array_key_exists('biometricStatusReport', $data)) { | ||||
|             foreach ($data['biometricStatusReport'] as $biometricStatusReport) { | ||||
|                 $object->addBiometricStatusReports(BiometricStatusReport::createFromArray($biometricStatusReport)); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $object; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array<string, mixed> | ||||
|      */ | ||||
|     public function jsonSerialize(): array | ||||
|     { | ||||
|         $data = [ | ||||
|             'aaid' => $this->aaid, | ||||
|             'aaguid' => $this->aaguid, | ||||
|             'attestationCertificateKeyIdentifiers' => $this->attestationCertificateKeyIdentifiers, | ||||
|             'statusReports' => array_map( | ||||
|                 static fn (StatusReport $object): array => $object->jsonSerialize(), | ||||
|                 $this->statusReports | ||||
|             ), | ||||
|             'timeOfLastStatusChange' => $this->timeOfLastStatusChange, | ||||
|             'rogueListURL' => $this->rogueListURL, | ||||
|             'rogueListHash' => $this->rogueListHash, | ||||
|         ]; | ||||
|  | ||||
|         return Utils::filterNullValues($data); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										19
									
								
								libraries/vendor/web-auth/metadata-service/src/Service/MetadataService.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								libraries/vendor/web-auth/metadata-service/src/Service/MetadataService.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Service; | ||||
|  | ||||
| use Webauthn\MetadataService\Statement\MetadataStatement; | ||||
|  | ||||
| interface MetadataService | ||||
| { | ||||
|     /** | ||||
|      * @return string[] The list of AAGUID supported by the service | ||||
|      */ | ||||
|     public function list(): iterable; | ||||
|  | ||||
|     public function has(string $aaguid): bool; | ||||
|  | ||||
|     public function get(string $aaguid): MetadataStatement; | ||||
| } | ||||
							
								
								
									
										73
									
								
								libraries/vendor/web-auth/metadata-service/src/Service/StringMetadataService.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								libraries/vendor/web-auth/metadata-service/src/Service/StringMetadataService.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,73 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Service; | ||||
|  | ||||
| use function array_key_exists; | ||||
| use Psr\EventDispatcher\EventDispatcherInterface; | ||||
| use Webauthn\MetadataService\Event\CanDispatchEvents; | ||||
| use Webauthn\MetadataService\Event\MetadataStatementFound; | ||||
| use Webauthn\MetadataService\Event\NullEventDispatcher; | ||||
| use Webauthn\MetadataService\Exception\MissingMetadataStatementException; | ||||
| use Webauthn\MetadataService\Statement\MetadataStatement; | ||||
|  | ||||
| final class StringMetadataService implements MetadataService, CanDispatchEvents | ||||
| { | ||||
|     /** | ||||
|      * @var MetadataStatement[] | ||||
|      */ | ||||
|     private array $statements = []; | ||||
|  | ||||
|     private EventDispatcherInterface $dispatcher; | ||||
|  | ||||
|     public function __construct(string ...$statements) | ||||
|     { | ||||
|         foreach ($statements as $statement) { | ||||
|             $this->addStatements(MetadataStatement::createFromString($statement)); | ||||
|         } | ||||
|         $this->dispatcher = new NullEventDispatcher(); | ||||
|     } | ||||
|  | ||||
|     public function setEventDispatcher(EventDispatcherInterface $eventDispatcher): void | ||||
|     { | ||||
|         $this->dispatcher = $eventDispatcher; | ||||
|     } | ||||
|  | ||||
|     public static function create(string ...$statements): self | ||||
|     { | ||||
|         return new self(...$statements); | ||||
|     } | ||||
|  | ||||
|     public function addStatements(MetadataStatement ...$statements): self | ||||
|     { | ||||
|         foreach ($statements as $statement) { | ||||
|             $aaguid = $statement->getAaguid(); | ||||
|             if ($aaguid === null) { | ||||
|                 continue; | ||||
|             } | ||||
|             $this->statements[$aaguid] = $statement; | ||||
|         } | ||||
|  | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
|     public function list(): iterable | ||||
|     { | ||||
|         yield from array_keys($this->statements); | ||||
|     } | ||||
|  | ||||
|     public function has(string $aaguid): bool | ||||
|     { | ||||
|         return array_key_exists($aaguid, $this->statements); | ||||
|     } | ||||
|  | ||||
|     public function get(string $aaguid): MetadataStatement | ||||
|     { | ||||
|         array_key_exists($aaguid, $this->statements) || throw MissingMetadataStatementException::create($aaguid); | ||||
|         $mds = $this->statements[$aaguid]; | ||||
|         $this->dispatcher->dispatch(MetadataStatementFound::create($mds)); | ||||
|  | ||||
|         return $mds; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										38
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/AbstractDescriptor.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/AbstractDescriptor.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,38 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Statement; | ||||
|  | ||||
| use JsonSerializable; | ||||
| use Webauthn\MetadataService\Exception\MetadataStatementLoadingException; | ||||
|  | ||||
| abstract class AbstractDescriptor implements JsonSerializable | ||||
| { | ||||
|     private readonly ?int $maxRetries; | ||||
|  | ||||
|     private readonly ?int $blockSlowdown; | ||||
|  | ||||
|     public function __construct(?int $maxRetries = null, ?int $blockSlowdown = null) | ||||
|     { | ||||
|         $maxRetries >= 0 || throw MetadataStatementLoadingException::create( | ||||
|             'Invalid data. The value of "maxRetries" must be a positive integer' | ||||
|         ); | ||||
|         $blockSlowdown >= 0 || throw MetadataStatementLoadingException::create( | ||||
|             'Invalid data. The value of "blockSlowdown" must be a positive integer' | ||||
|         ); | ||||
|  | ||||
|         $this->maxRetries = $maxRetries; | ||||
|         $this->blockSlowdown = $blockSlowdown; | ||||
|     } | ||||
|  | ||||
|     public function getMaxRetries(): ?int | ||||
|     { | ||||
|         return $this->maxRetries; | ||||
|     } | ||||
|  | ||||
|     public function getBlockSlowdown(): ?int | ||||
|     { | ||||
|         return $this->blockSlowdown; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										54
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/AlternativeDescriptions.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/AlternativeDescriptions.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,54 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Statement; | ||||
|  | ||||
| use JsonSerializable; | ||||
|  | ||||
| /** | ||||
|  * @final | ||||
|  */ | ||||
| class AlternativeDescriptions implements JsonSerializable | ||||
| { | ||||
|     /** | ||||
|      * @var array<string, string> | ||||
|      */ | ||||
|     private array $descriptions = []; | ||||
|  | ||||
|     /** | ||||
|      * @param array<string, string> $descriptions | ||||
|      */ | ||||
|     public static function create(array $descriptions = []): self | ||||
|     { | ||||
|         $object = new self(); | ||||
|         foreach ($descriptions as $k => $v) { | ||||
|             $object->add($k, $v); | ||||
|         } | ||||
|  | ||||
|         return $object; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array<string, string> | ||||
|      */ | ||||
|     public function all(): array | ||||
|     { | ||||
|         return $this->descriptions; | ||||
|     } | ||||
|  | ||||
|     public function add(string $locale, string $description): self | ||||
|     { | ||||
|         $this->descriptions[$locale] = $description; | ||||
|  | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array<string, string> | ||||
|      */ | ||||
|     public function jsonSerialize(): array | ||||
|     { | ||||
|         return $this->descriptions; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										46
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/AuthenticatorGetInfo.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/AuthenticatorGetInfo.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,46 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Statement; | ||||
|  | ||||
| use JsonSerializable; | ||||
|  | ||||
| /** | ||||
|  * @final | ||||
|  */ | ||||
| class AuthenticatorGetInfo implements JsonSerializable | ||||
| { | ||||
|     /** | ||||
|      * @var string[] | ||||
|      */ | ||||
|     private array $info = []; | ||||
|  | ||||
|     /** | ||||
|      * @param array<string|int, mixed> $data | ||||
|      */ | ||||
|     public static function create(array $data = []): self | ||||
|     { | ||||
|         $object = new self(); | ||||
|         foreach ($data as $k => $v) { | ||||
|             $object->add($k, $v); | ||||
|         } | ||||
|  | ||||
|         return $object; | ||||
|     } | ||||
|  | ||||
|     public function add(string|int $key, mixed $value): self | ||||
|     { | ||||
|         $this->info[$key] = $value; | ||||
|  | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string[] | ||||
|      */ | ||||
|     public function jsonSerialize(): array | ||||
|     { | ||||
|         return $this->info; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										68
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/AuthenticatorStatus.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/AuthenticatorStatus.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,68 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Statement; | ||||
|  | ||||
| abstract class AuthenticatorStatus | ||||
| { | ||||
|     final public const NOT_FIDO_CERTIFIED = 'NOT_FIDO_CERTIFIED'; | ||||
|  | ||||
|     final public const FIDO_CERTIFIED = 'FIDO_CERTIFIED'; | ||||
|  | ||||
|     final public const USER_VERIFICATION_BYPASS = 'USER_VERIFICATION_BYPASS'; | ||||
|  | ||||
|     final public const ATTESTATION_KEY_COMPROMISE = 'ATTESTATION_KEY_COMPROMISE'; | ||||
|  | ||||
|     final public const USER_KEY_REMOTE_COMPROMISE = 'USER_KEY_REMOTE_COMPROMISE'; | ||||
|  | ||||
|     final public const USER_KEY_PHYSICAL_COMPROMISE = 'USER_KEY_PHYSICAL_COMPROMISE'; | ||||
|  | ||||
|     final public const UPDATE_AVAILABLE = 'UPDATE_AVAILABLE'; | ||||
|  | ||||
|     final public const REVOKED = 'REVOKED'; | ||||
|  | ||||
|     final public const SELF_ASSERTION_SUBMITTED = 'SELF_ASSERTION_SUBMITTED'; | ||||
|  | ||||
|     final public const FIDO_CERTIFIED_L1 = 'FIDO_CERTIFIED_L1'; | ||||
|  | ||||
|     final public const FIDO_CERTIFIED_L1plus = 'FIDO_CERTIFIED_L1plus'; | ||||
|  | ||||
|     final public const FIDO_CERTIFIED_L2 = 'FIDO_CERTIFIED_L2'; | ||||
|  | ||||
|     final public const FIDO_CERTIFIED_L2plus = 'FIDO_CERTIFIED_L2plus'; | ||||
|  | ||||
|     final public const FIDO_CERTIFIED_L3 = 'FIDO_CERTIFIED_L3'; | ||||
|  | ||||
|     final public const FIDO_CERTIFIED_L3plus = 'FIDO_CERTIFIED_L3plus'; | ||||
|  | ||||
|     final public const FIDO_CERTIFIED_L4 = 'FIDO_CERTIFIED_L4'; | ||||
|  | ||||
|     final public const FIDO_CERTIFIED_L5 = 'FIDO_CERTIFIED_L5'; | ||||
|  | ||||
|     /** | ||||
|      * @return string[] | ||||
|      */ | ||||
|     public static function list(): array | ||||
|     { | ||||
|         return [ | ||||
|             self::NOT_FIDO_CERTIFIED, | ||||
|             self::FIDO_CERTIFIED, | ||||
|             self::USER_VERIFICATION_BYPASS, | ||||
|             self::ATTESTATION_KEY_COMPROMISE, | ||||
|             self::USER_KEY_REMOTE_COMPROMISE, | ||||
|             self::USER_KEY_PHYSICAL_COMPROMISE, | ||||
|             self::UPDATE_AVAILABLE, | ||||
|             self::REVOKED, | ||||
|             self::SELF_ASSERTION_SUBMITTED, | ||||
|             self::FIDO_CERTIFIED_L1, | ||||
|             self::FIDO_CERTIFIED_L1plus, | ||||
|             self::FIDO_CERTIFIED_L2, | ||||
|             self::FIDO_CERTIFIED_L2plus, | ||||
|             self::FIDO_CERTIFIED_L3, | ||||
|             self::FIDO_CERTIFIED_L3plus, | ||||
|             self::FIDO_CERTIFIED_L4, | ||||
|             self::FIDO_CERTIFIED_L5, | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										68
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/BiometricAccuracyDescriptor.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/BiometricAccuracyDescriptor.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,68 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Statement; | ||||
|  | ||||
| use Webauthn\MetadataService\Utils; | ||||
|  | ||||
| /** | ||||
|  * @final | ||||
|  */ | ||||
| class BiometricAccuracyDescriptor extends AbstractDescriptor | ||||
| { | ||||
|     public function __construct( | ||||
|         private readonly ?float $selfAttestedFRR, | ||||
|         private readonly ?float $selfAttestedFAR, | ||||
|         private readonly ?float $maxTemplates, | ||||
|         ?int $maxRetries = null, | ||||
|         ?int $blockSlowdown = null | ||||
|     ) { | ||||
|         parent::__construct($maxRetries, $blockSlowdown); | ||||
|     } | ||||
|  | ||||
|     public function getSelfAttestedFRR(): ?float | ||||
|     { | ||||
|         return $this->selfAttestedFRR; | ||||
|     } | ||||
|  | ||||
|     public function getSelfAttestedFAR(): ?float | ||||
|     { | ||||
|         return $this->selfAttestedFAR; | ||||
|     } | ||||
|  | ||||
|     public function getMaxTemplates(): ?float | ||||
|     { | ||||
|         return $this->maxTemplates; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array<string, mixed> $data | ||||
|      */ | ||||
|     public static function createFromArray(array $data): self | ||||
|     { | ||||
|         return new self( | ||||
|             $data['selfAttestedFRR'] ?? null, | ||||
|             $data['selfAttestedFAR'] ?? null, | ||||
|             $data['maxTemplates'] ?? null, | ||||
|             $data['maxRetries'] ?? null, | ||||
|             $data['blockSlowdown'] ?? null | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array<string, mixed> | ||||
|      */ | ||||
|     public function jsonSerialize(): array | ||||
|     { | ||||
|         $data = [ | ||||
|             'selfAttestedFRR' => $this->selfAttestedFRR, | ||||
|             'selfAttestedFAR' => $this->selfAttestedFAR, | ||||
|             'maxTemplates' => $this->maxTemplates, | ||||
|             'maxRetries' => $this->getMaxRetries(), | ||||
|             'blockSlowdown' => $this->getBlockSlowdown(), | ||||
|         ]; | ||||
|  | ||||
|         return Utils::filterNullValues($data); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										97
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/BiometricStatusReport.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/BiometricStatusReport.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,97 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Statement; | ||||
|  | ||||
| use JsonSerializable; | ||||
|  | ||||
| /** | ||||
|  * @final | ||||
|  */ | ||||
| class BiometricStatusReport implements JsonSerializable | ||||
| { | ||||
|     private ?int $certLevel = null; | ||||
|  | ||||
|     private ?int $modality = null; | ||||
|  | ||||
|     private ?string $effectiveDate = null; | ||||
|  | ||||
|     private ?string $certificationDescriptor = null; | ||||
|  | ||||
|     private ?string $certificateNumber = null; | ||||
|  | ||||
|     private ?string $certificationPolicyVersion = null; | ||||
|  | ||||
|     private ?string $certificationRequirementsVersion = null; | ||||
|  | ||||
|     public function getCertLevel(): int|null | ||||
|     { | ||||
|         return $this->certLevel; | ||||
|     } | ||||
|  | ||||
|     public function getModality(): int|null | ||||
|     { | ||||
|         return $this->modality; | ||||
|     } | ||||
|  | ||||
|     public function getEffectiveDate(): ?string | ||||
|     { | ||||
|         return $this->effectiveDate; | ||||
|     } | ||||
|  | ||||
|     public function getCertificationDescriptor(): ?string | ||||
|     { | ||||
|         return $this->certificationDescriptor; | ||||
|     } | ||||
|  | ||||
|     public function getCertificateNumber(): ?string | ||||
|     { | ||||
|         return $this->certificateNumber; | ||||
|     } | ||||
|  | ||||
|     public function getCertificationPolicyVersion(): ?string | ||||
|     { | ||||
|         return $this->certificationPolicyVersion; | ||||
|     } | ||||
|  | ||||
|     public function getCertificationRequirementsVersion(): ?string | ||||
|     { | ||||
|         return $this->certificationRequirementsVersion; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array<string, mixed> $data | ||||
|      */ | ||||
|     public static function createFromArray(array $data): self | ||||
|     { | ||||
|         $object = new self(); | ||||
|         $object->certLevel = $data['certLevel'] ?? null; | ||||
|         $object->modality = $data['modality'] ?? null; | ||||
|         $object->effectiveDate = $data['effectiveDate'] ?? null; | ||||
|         $object->certificationDescriptor = $data['certificationDescriptor'] ?? null; | ||||
|         $object->certificateNumber = $data['certificateNumber'] ?? null; | ||||
|         $object->certificationPolicyVersion = $data['certificationPolicyVersion'] ?? null; | ||||
|         $object->certificationRequirementsVersion = $data['certificationRequirementsVersion'] ?? null; | ||||
|  | ||||
|         return $object; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array<string, mixed> | ||||
|      */ | ||||
|     public function jsonSerialize(): array | ||||
|     { | ||||
|         $data = [ | ||||
|             'certLevel' => $this->certLevel, | ||||
|             'modality' => $this->modality, | ||||
|             'effectiveDate' => $this->effectiveDate, | ||||
|             'certificationDescriptor' => $this->certificationDescriptor, | ||||
|             'certificateNumber' => $this->certificateNumber, | ||||
|             'certificationPolicyVersion' => $this->certificationPolicyVersion, | ||||
|             'certificationRequirementsVersion' => $this->certificationRequirementsVersion, | ||||
|         ]; | ||||
|  | ||||
|         return array_filter($data, static fn ($var): bool => $var !== null); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										77
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/CodeAccuracyDescriptor.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/CodeAccuracyDescriptor.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,77 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Statement; | ||||
|  | ||||
| use function array_key_exists; | ||||
| use Webauthn\MetadataService\Exception\MetadataStatementLoadingException; | ||||
| use Webauthn\MetadataService\Utils; | ||||
|  | ||||
| /** | ||||
|  * @final | ||||
|  */ | ||||
| class CodeAccuracyDescriptor extends AbstractDescriptor | ||||
| { | ||||
|     private readonly int $base; | ||||
|  | ||||
|     private readonly int $minLength; | ||||
|  | ||||
|     public function __construct(int $base, int $minLength, ?int $maxRetries = null, ?int $blockSlowdown = null) | ||||
|     { | ||||
|         $base >= 0 || throw MetadataStatementLoadingException::create( | ||||
|             'Invalid data. The value of "base" must be a positive integer' | ||||
|         ); | ||||
|         $minLength >= 0 || throw MetadataStatementLoadingException::create( | ||||
|             'Invalid data. The value of "minLength" must be a positive integer' | ||||
|         ); | ||||
|         $this->base = $base; | ||||
|         $this->minLength = $minLength; | ||||
|         parent::__construct($maxRetries, $blockSlowdown); | ||||
|     } | ||||
|  | ||||
|     public function getBase(): int | ||||
|     { | ||||
|         return $this->base; | ||||
|     } | ||||
|  | ||||
|     public function getMinLength(): int | ||||
|     { | ||||
|         return $this->minLength; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array<string, mixed> $data | ||||
|      */ | ||||
|     public static function createFromArray(array $data): self | ||||
|     { | ||||
|         array_key_exists('base', $data) || throw MetadataStatementLoadingException::create( | ||||
|             'The parameter "base" is missing' | ||||
|         ); | ||||
|         array_key_exists('minLength', $data) || throw MetadataStatementLoadingException::create( | ||||
|             'The parameter "minLength" is missing' | ||||
|         ); | ||||
|  | ||||
|         return new self( | ||||
|             $data['base'], | ||||
|             $data['minLength'], | ||||
|             $data['maxRetries'] ?? null, | ||||
|             $data['blockSlowdown'] ?? null | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array<string, mixed> | ||||
|      */ | ||||
|     public function jsonSerialize(): array | ||||
|     { | ||||
|         $data = [ | ||||
|             'base' => $this->base, | ||||
|             'minLength' => $this->minLength, | ||||
|             'maxRetries' => $this->getMaxRetries(), | ||||
|             'blockSlowdown' => $this->getBlockSlowdown(), | ||||
|         ]; | ||||
|  | ||||
|         return Utils::filterNullValues($data); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										180
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/DisplayPNGCharacteristicsDescriptor.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/DisplayPNGCharacteristicsDescriptor.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,180 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Statement; | ||||
|  | ||||
| use function array_key_exists; | ||||
| use function is_array; | ||||
| use JsonSerializable; | ||||
| use Webauthn\MetadataService\Exception\MetadataStatementLoadingException; | ||||
| use Webauthn\MetadataService\Utils; | ||||
|  | ||||
| /** | ||||
|  * @final | ||||
|  */ | ||||
| class DisplayPNGCharacteristicsDescriptor implements JsonSerializable | ||||
| { | ||||
|     private readonly int $width; | ||||
|  | ||||
|     private readonly int $height; | ||||
|  | ||||
|     private readonly int $bitDepth; | ||||
|  | ||||
|     private readonly int $colorType; | ||||
|  | ||||
|     private readonly int $compression; | ||||
|  | ||||
|     private readonly int $filter; | ||||
|  | ||||
|     private readonly int $interlace; | ||||
|  | ||||
|     /** | ||||
|      * @var RgbPaletteEntry[] | ||||
|      */ | ||||
|     private array $plte = []; | ||||
|  | ||||
|     public function __construct( | ||||
|         int $width, | ||||
|         int $height, | ||||
|         int $bitDepth, | ||||
|         int $colorType, | ||||
|         int $compression, | ||||
|         int $filter, | ||||
|         int $interlace | ||||
|     ) { | ||||
|         $width >= 0 || throw MetadataStatementLoadingException::create('Invalid width'); | ||||
|         $height >= 0 || throw MetadataStatementLoadingException::create('Invalid height'); | ||||
|         ($bitDepth >= 0 && $bitDepth <= 254) || throw MetadataStatementLoadingException::create('Invalid bit depth'); | ||||
|         ($colorType >= 0 && $colorType <= 254) || throw MetadataStatementLoadingException::create( | ||||
|             'Invalid color type' | ||||
|         ); | ||||
|         ($compression >= 0 && $compression <= 254) || throw MetadataStatementLoadingException::create( | ||||
|             'Invalid compression' | ||||
|         ); | ||||
|         ($filter >= 0 && $filter <= 254) || throw MetadataStatementLoadingException::create('Invalid filter'); | ||||
|         ($interlace >= 0 && $interlace <= 254) || throw MetadataStatementLoadingException::create( | ||||
|             'Invalid interlace' | ||||
|         ); | ||||
|  | ||||
|         $this->width = $width; | ||||
|         $this->height = $height; | ||||
|         $this->bitDepth = $bitDepth; | ||||
|         $this->colorType = $colorType; | ||||
|         $this->compression = $compression; | ||||
|         $this->filter = $filter; | ||||
|         $this->interlace = $interlace; | ||||
|     } | ||||
|  | ||||
|     public function addPalettes(RgbPaletteEntry ...$rgbPaletteEntries): self | ||||
|     { | ||||
|         foreach ($rgbPaletteEntries as $rgbPaletteEntry) { | ||||
|             $this->plte[] = $rgbPaletteEntry; | ||||
|         } | ||||
|  | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
|     public function getWidth(): int | ||||
|     { | ||||
|         return $this->width; | ||||
|     } | ||||
|  | ||||
|     public function getHeight(): int | ||||
|     { | ||||
|         return $this->height; | ||||
|     } | ||||
|  | ||||
|     public function getBitDepth(): int | ||||
|     { | ||||
|         return $this->bitDepth; | ||||
|     } | ||||
|  | ||||
|     public function getColorType(): int | ||||
|     { | ||||
|         return $this->colorType; | ||||
|     } | ||||
|  | ||||
|     public function getCompression(): int | ||||
|     { | ||||
|         return $this->compression; | ||||
|     } | ||||
|  | ||||
|     public function getFilter(): int | ||||
|     { | ||||
|         return $this->filter; | ||||
|     } | ||||
|  | ||||
|     public function getInterlace(): int | ||||
|     { | ||||
|         return $this->interlace; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return RgbPaletteEntry[] | ||||
|      */ | ||||
|     public function getPaletteEntries(): array | ||||
|     { | ||||
|         return $this->plte; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array<string, mixed> $data | ||||
|      */ | ||||
|     public static function createFromArray(array $data): self | ||||
|     { | ||||
|         $data = Utils::filterNullValues($data); | ||||
|         foreach ([ | ||||
|             'width', | ||||
|             'compression', | ||||
|             'height', | ||||
|             'bitDepth', | ||||
|             'colorType', | ||||
|             'compression', | ||||
|             'filter', | ||||
|             'interlace', | ||||
|         ] as $key) { | ||||
|             array_key_exists($key, $data) || throw MetadataStatementLoadingException::create(sprintf( | ||||
|                 'Invalid data. The key "%s" is missing', | ||||
|                 $key | ||||
|             )); | ||||
|         } | ||||
|         $object = new self( | ||||
|             $data['width'], | ||||
|             $data['height'], | ||||
|             $data['bitDepth'], | ||||
|             $data['colorType'], | ||||
|             $data['compression'], | ||||
|             $data['filter'], | ||||
|             $data['interlace'] | ||||
|         ); | ||||
|         if (isset($data['plte'])) { | ||||
|             $plte = $data['plte']; | ||||
|             is_array($plte) || throw MetadataStatementLoadingException::create('Invalid "plte" parameter'); | ||||
|             foreach ($plte as $item) { | ||||
|                 $object->addPalettes(RgbPaletteEntry::createFromArray($item)); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $object; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array<string, mixed> | ||||
|      */ | ||||
|     public function jsonSerialize(): array | ||||
|     { | ||||
|         $data = [ | ||||
|             'width' => $this->width, | ||||
|             'height' => $this->height, | ||||
|             'bitDepth' => $this->bitDepth, | ||||
|             'colorType' => $this->colorType, | ||||
|             'compression' => $this->compression, | ||||
|             'filter' => $this->filter, | ||||
|             'interlace' => $this->interlace, | ||||
|             'plte' => $this->plte, | ||||
|         ]; | ||||
|  | ||||
|         return Utils::filterNullValues($data); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										98
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/EcdaaTrustAnchor.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/EcdaaTrustAnchor.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,98 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Statement; | ||||
|  | ||||
| use function array_key_exists; | ||||
| use JsonSerializable; | ||||
| use ParagonIE\ConstantTime\Base64UrlSafe; | ||||
| use Webauthn\MetadataService\Exception\MetadataStatementLoadingException; | ||||
| use Webauthn\MetadataService\Utils; | ||||
|  | ||||
| /** | ||||
|  * @deprecated since 4.2.0 and will be removed in 5.0.0. The ECDAA Trust Anchor does no longer exist in Webauthn specification. | ||||
|  * @final | ||||
|  */ | ||||
| class EcdaaTrustAnchor implements JsonSerializable | ||||
| { | ||||
|     public function __construct( | ||||
|         private readonly string $X, | ||||
|         private readonly string $Y, | ||||
|         private readonly string $c, | ||||
|         private readonly string $sx, | ||||
|         private readonly string $sy, | ||||
|         private readonly string $G1Curve | ||||
|     ) { | ||||
|     } | ||||
|  | ||||
|     public function getX(): string | ||||
|     { | ||||
|         return $this->X; | ||||
|     } | ||||
|  | ||||
|     public function getY(): string | ||||
|     { | ||||
|         return $this->Y; | ||||
|     } | ||||
|  | ||||
|     public function getC(): string | ||||
|     { | ||||
|         return $this->c; | ||||
|     } | ||||
|  | ||||
|     public function getSx(): string | ||||
|     { | ||||
|         return $this->sx; | ||||
|     } | ||||
|  | ||||
|     public function getSy(): string | ||||
|     { | ||||
|         return $this->sy; | ||||
|     } | ||||
|  | ||||
|     public function getG1Curve(): string | ||||
|     { | ||||
|         return $this->G1Curve; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array<string, mixed> $data | ||||
|      */ | ||||
|     public static function createFromArray(array $data): self | ||||
|     { | ||||
|         $data = Utils::filterNullValues($data); | ||||
|         foreach (['X', 'Y', 'c', 'sx', 'sy', 'G1Curve'] as $key) { | ||||
|             array_key_exists($key, $data) || throw MetadataStatementLoadingException::create(sprintf( | ||||
|                 'Invalid data. The key "%s" is missing', | ||||
|                 $key | ||||
|             )); | ||||
|         } | ||||
|  | ||||
|         return new self( | ||||
|             Base64UrlSafe::decode($data['X']), | ||||
|             Base64UrlSafe::decode($data['Y']), | ||||
|             Base64UrlSafe::decode($data['c']), | ||||
|             Base64UrlSafe::decode($data['sx']), | ||||
|             Base64UrlSafe::decode($data['sy']), | ||||
|             $data['G1Curve'] | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array<string, string> | ||||
|      */ | ||||
|     public function jsonSerialize(): array | ||||
|     { | ||||
|         $data = [ | ||||
|             'X' => Base64UrlSafe::encodeUnpadded($this->X), | ||||
|             'Y' => Base64UrlSafe::encodeUnpadded($this->Y), | ||||
|             'c' => Base64UrlSafe::encodeUnpadded($this->c), | ||||
|             'sx' => Base64UrlSafe::encodeUnpadded($this->sx), | ||||
|             'sy' => Base64UrlSafe::encodeUnpadded($this->sy), | ||||
|             'G1Curve' => $this->G1Curve, | ||||
|         ]; | ||||
|  | ||||
|         return Utils::filterNullValues($data); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										83
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/ExtensionDescriptor.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/ExtensionDescriptor.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,83 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Statement; | ||||
|  | ||||
| use function array_key_exists; | ||||
| use JsonSerializable; | ||||
| use Webauthn\MetadataService\Exception\MetadataStatementLoadingException; | ||||
| use Webauthn\MetadataService\Utils; | ||||
|  | ||||
| /** | ||||
|  * @final | ||||
|  */ | ||||
| class ExtensionDescriptor implements JsonSerializable | ||||
| { | ||||
|     private readonly ?int $tag; | ||||
|  | ||||
|     public function __construct( | ||||
|         private readonly string $id, | ||||
|         ?int $tag, | ||||
|         private readonly ?string $data, | ||||
|         private readonly bool $failIfUnknown | ||||
|     ) { | ||||
|         if ($tag !== null) { | ||||
|             $tag >= 0 || throw MetadataStatementLoadingException::create( | ||||
|                 'Invalid data. The parameter "tag" shall be a positive integer' | ||||
|             ); | ||||
|         } | ||||
|         $this->tag = $tag; | ||||
|     } | ||||
|  | ||||
|     public function getId(): string | ||||
|     { | ||||
|         return $this->id; | ||||
|     } | ||||
|  | ||||
|     public function getTag(): ?int | ||||
|     { | ||||
|         return $this->tag; | ||||
|     } | ||||
|  | ||||
|     public function getData(): ?string | ||||
|     { | ||||
|         return $this->data; | ||||
|     } | ||||
|  | ||||
|     public function isFailIfUnknown(): bool | ||||
|     { | ||||
|         return $this->failIfUnknown; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array<string, mixed> $data | ||||
|      */ | ||||
|     public static function createFromArray(array $data): self | ||||
|     { | ||||
|         $data = Utils::filterNullValues($data); | ||||
|         array_key_exists('id', $data) || throw MetadataStatementLoadingException::create( | ||||
|             'Invalid data. The parameter "id" is missing' | ||||
|         ); | ||||
|         array_key_exists('fail_if_unknown', $data) || throw MetadataStatementLoadingException::create( | ||||
|             'Invalid data. The parameter "fail_if_unknown" is missing' | ||||
|         ); | ||||
|  | ||||
|         return new self($data['id'], $data['tag'] ?? null, $data['data'] ?? null, $data['fail_if_unknown']); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array<string, mixed> | ||||
|      */ | ||||
|     public function jsonSerialize(): array | ||||
|     { | ||||
|         $result = [ | ||||
|             'id' => $this->id, | ||||
|             'tag' => $this->tag, | ||||
|             'data' => $this->data, | ||||
|             'fail_if_unknown' => $this->failIfUnknown, | ||||
|         ]; | ||||
|  | ||||
|         return Utils::filterNullValues($result); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										556
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/MetadataStatement.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										556
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/MetadataStatement.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,556 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Statement; | ||||
|  | ||||
| use function array_key_exists; | ||||
| use function is_array; | ||||
| use function is_string; | ||||
| use const JSON_THROW_ON_ERROR; | ||||
| use JsonSerializable; | ||||
| use Webauthn\MetadataService\CertificateChain\CertificateToolbox; | ||||
| use Webauthn\MetadataService\Exception\MetadataStatementLoadingException; | ||||
| use Webauthn\MetadataService\Utils; | ||||
|  | ||||
| /** | ||||
|  * @final | ||||
|  */ | ||||
| class MetadataStatement implements JsonSerializable | ||||
| { | ||||
|     final public const KEY_PROTECTION_SOFTWARE = 'software'; | ||||
|  | ||||
|     final public const KEY_PROTECTION_HARDWARE = 'hardware'; | ||||
|  | ||||
|     final public const KEY_PROTECTION_TEE = 'tee'; | ||||
|  | ||||
|     final public const KEY_PROTECTION_SECURE_ELEMENT = 'secure_element'; | ||||
|  | ||||
|     final public const KEY_PROTECTION_REMOTE_HANDLE = 'remote_handle'; | ||||
|  | ||||
|     final public const MATCHER_PROTECTION_SOFTWARE = 'software'; | ||||
|  | ||||
|     final public const MATCHER_PROTECTION_TEE = 'tee'; | ||||
|  | ||||
|     final public const MATCHER_PROTECTION_ON_CHIP = 'on_chip'; | ||||
|  | ||||
|     final public const ATTACHMENT_HINT_INTERNAL = 'internal'; | ||||
|  | ||||
|     final public const ATTACHMENT_HINT_EXTERNAL = 'external'; | ||||
|  | ||||
|     final public const ATTACHMENT_HINT_WIRED = 'wired'; | ||||
|  | ||||
|     final public const ATTACHMENT_HINT_WIRELESS = 'wireless'; | ||||
|  | ||||
|     final public const ATTACHMENT_HINT_NFC = 'nfc'; | ||||
|  | ||||
|     final public const ATTACHMENT_HINT_BLUETOOTH = 'bluetooth'; | ||||
|  | ||||
|     final public const ATTACHMENT_HINT_NETWORK = 'network'; | ||||
|  | ||||
|     final public const ATTACHMENT_HINT_READY = 'ready'; | ||||
|  | ||||
|     final public const ATTACHMENT_HINT_WIFI_DIRECT = 'wifi_direct'; | ||||
|  | ||||
|     final public const TRANSACTION_CONFIRMATION_DISPLAY_ANY = 'any'; | ||||
|  | ||||
|     final public const TRANSACTION_CONFIRMATION_DISPLAY_PRIVILEGED_SOFTWARE = 'privileged_software'; | ||||
|  | ||||
|     final public const TRANSACTION_CONFIRMATION_DISPLAY_TEE = 'tee'; | ||||
|  | ||||
|     final public const TRANSACTION_CONFIRMATION_DISPLAY_HARDWARE = 'hardware'; | ||||
|  | ||||
|     final public const TRANSACTION_CONFIRMATION_DISPLAY_REMOTE = 'remote'; | ||||
|  | ||||
|     final public const ALG_SIGN_SECP256R1_ECDSA_SHA256_RAW = 'secp256r1_ecdsa_sha256_raw'; | ||||
|  | ||||
|     final public const ALG_SIGN_SECP256R1_ECDSA_SHA256_DER = 'secp256r1_ecdsa_sha256_der'; | ||||
|  | ||||
|     final public const ALG_SIGN_RSASSA_PSS_SHA256_RAW = 'rsassa_pss_sha256_raw'; | ||||
|  | ||||
|     final public const ALG_SIGN_RSASSA_PSS_SHA256_DER = 'rsassa_pss_sha256_der'; | ||||
|  | ||||
|     final public const ALG_SIGN_SECP256K1_ECDSA_SHA256_RAW = 'secp256k1_ecdsa_sha256_raw'; | ||||
|  | ||||
|     final public const ALG_SIGN_SECP256K1_ECDSA_SHA256_DER = 'secp256k1_ecdsa_sha256_der'; | ||||
|  | ||||
|     final public const ALG_SIGN_SM2_SM3_RAW = 'sm2_sm3_raw'; | ||||
|  | ||||
|     final public const ALG_SIGN_RSA_EMSA_PKCS1_SHA256_RAW = 'rsa_emsa_pkcs1_sha256_raw'; | ||||
|  | ||||
|     final public const ALG_SIGN_RSA_EMSA_PKCS1_SHA256_DER = 'rsa_emsa_pkcs1_sha256_der'; | ||||
|  | ||||
|     final public const ALG_SIGN_RSASSA_PSS_SHA384_RAW = 'rsassa_pss_sha384_raw'; | ||||
|  | ||||
|     final public const ALG_SIGN_RSASSA_PSS_SHA512_RAW = 'rsassa_pss_sha256_raw'; | ||||
|  | ||||
|     final public const ALG_SIGN_RSASSA_PKCSV15_SHA256_RAW = 'rsassa_pkcsv15_sha256_raw'; | ||||
|  | ||||
|     final public const ALG_SIGN_RSASSA_PKCSV15_SHA384_RAW = 'rsassa_pkcsv15_sha384_raw'; | ||||
|  | ||||
|     final public const ALG_SIGN_RSASSA_PKCSV15_SHA512_RAW = 'rsassa_pkcsv15_sha512_raw'; | ||||
|  | ||||
|     final public const ALG_SIGN_RSASSA_PKCSV15_SHA1_RAW = 'rsassa_pkcsv15_sha1_raw'; | ||||
|  | ||||
|     final public const ALG_SIGN_SECP384R1_ECDSA_SHA384_RAW = 'secp384r1_ecdsa_sha384_raw'; | ||||
|  | ||||
|     final public const ALG_SIGN_SECP521R1_ECDSA_SHA512_RAW = 'secp512r1_ecdsa_sha256_raw'; | ||||
|  | ||||
|     final public const ALG_SIGN_ED25519_EDDSA_SHA256_RAW = 'ed25519_eddsa_sha512_raw'; | ||||
|  | ||||
|     final public const ALG_KEY_ECC_X962_RAW = 'ecc_x962_raw'; | ||||
|  | ||||
|     final public const ALG_KEY_ECC_X962_DER = 'ecc_x962_der'; | ||||
|  | ||||
|     final public const ALG_KEY_RSA_2048_RAW = 'rsa_2048_raw'; | ||||
|  | ||||
|     final public const ALG_KEY_RSA_2048_DER = 'rsa_2048_der'; | ||||
|  | ||||
|     final public const ALG_KEY_COSE = 'cose'; | ||||
|  | ||||
|     final public const ATTESTATION_BASIC_FULL = 'basic_full'; | ||||
|  | ||||
|     final public const ATTESTATION_BASIC_SURROGATE = 'basic_surrogate'; | ||||
|  | ||||
|     /** | ||||
|      * @deprecated since 4.2.0 and will be removed in 5.0.0. The ECDAA Trust Anchor does no longer exist in Webauthn specification. | ||||
|      */ | ||||
|     final public const ATTESTATION_ECDAA = 'ecdaa'; | ||||
|  | ||||
|     final public const ATTESTATION_ATTCA = 'attca'; | ||||
|  | ||||
|     final public const ATTESTATION_ANONCA = 'anonca'; | ||||
|  | ||||
|     private ?string $legalHeader = null; | ||||
|  | ||||
|     private ?string $aaid = null; | ||||
|  | ||||
|     private ?string $aaguid = null; | ||||
|  | ||||
|     /** | ||||
|      * @var string[] | ||||
|      */ | ||||
|     private array $attestationCertificateKeyIdentifiers = []; | ||||
|  | ||||
|     private AlternativeDescriptions $alternativeDescriptions; | ||||
|  | ||||
|     /** | ||||
|      * @var string[] | ||||
|      */ | ||||
|     private array $keyProtection = []; | ||||
|  | ||||
|     private ?bool $isKeyRestricted = null; | ||||
|  | ||||
|     private ?bool $isFreshUserVerificationRequired = null; | ||||
|  | ||||
|     private ?int $cryptoStrength = null; | ||||
|  | ||||
|     /** | ||||
|      * @var string[] | ||||
|      */ | ||||
|     private array $attachmentHint = []; | ||||
|  | ||||
|     private ?string $tcDisplayContentType = null; | ||||
|  | ||||
|     /** | ||||
|      * @var DisplayPNGCharacteristicsDescriptor[] | ||||
|      */ | ||||
|     private array $tcDisplayPNGCharacteristics = []; | ||||
|  | ||||
|     /** | ||||
|      * @var EcdaaTrustAnchor[] | ||||
|      */ | ||||
|     private array $ecdaaTrustAnchors = []; | ||||
|  | ||||
|     private ?string $icon = null; | ||||
|  | ||||
|     /** | ||||
|      * @var ExtensionDescriptor[] | ||||
|      */ | ||||
|     private array $supportedExtensions = []; | ||||
|  | ||||
|     private null|AuthenticatorGetInfo $authenticatorGetInfo = null; | ||||
|  | ||||
|     /** | ||||
|      * @param Version[] $upv | ||||
|      * @param string[] $authenticationAlgorithms | ||||
|      * @param string[] $publicKeyAlgAndEncodings | ||||
|      * @param string[] $attestationTypes | ||||
|      * @param VerificationMethodANDCombinations[] $userVerificationDetails | ||||
|      * @param string[] $matcherProtection | ||||
|      * @param string[] $tcDisplay | ||||
|      * @param string[] $attestationRootCertificates | ||||
|      */ | ||||
|     public function __construct( | ||||
|         private readonly string $description, | ||||
|         private readonly int $authenticatorVersion, | ||||
|         private readonly string $protocolFamily, | ||||
|         private readonly int $schema, | ||||
|         private readonly array $upv, | ||||
|         private readonly array $authenticationAlgorithms, | ||||
|         private readonly array $publicKeyAlgAndEncodings, | ||||
|         private readonly array $attestationTypes, | ||||
|         private readonly array $userVerificationDetails, | ||||
|         private readonly array $matcherProtection, | ||||
|         private readonly array $tcDisplay, | ||||
|         private readonly array $attestationRootCertificates, | ||||
|     ) { | ||||
|         $this->alternativeDescriptions = new AlternativeDescriptions(); | ||||
|         $this->authenticatorGetInfo = new AuthenticatorGetInfo(); | ||||
|     } | ||||
|  | ||||
|     public static function createFromString(string $statement): self | ||||
|     { | ||||
|         $data = json_decode($statement, true, 512, JSON_THROW_ON_ERROR); | ||||
|  | ||||
|         return self::createFromArray($data); | ||||
|     } | ||||
|  | ||||
|     public function getLegalHeader(): ?string | ||||
|     { | ||||
|         return $this->legalHeader; | ||||
|     } | ||||
|  | ||||
|     public function getAaid(): ?string | ||||
|     { | ||||
|         return $this->aaid; | ||||
|     } | ||||
|  | ||||
|     public function getAaguid(): ?string | ||||
|     { | ||||
|         return $this->aaguid; | ||||
|     } | ||||
|  | ||||
|     public function isKeyRestricted(): ?bool | ||||
|     { | ||||
|         return $this->isKeyRestricted; | ||||
|     } | ||||
|  | ||||
|     public function isFreshUserVerificationRequired(): ?bool | ||||
|     { | ||||
|         return $this->isFreshUserVerificationRequired; | ||||
|     } | ||||
|  | ||||
|     public function getAuthenticatorGetInfo(): AuthenticatorGetInfo|null | ||||
|     { | ||||
|         return $this->authenticatorGetInfo; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string[] | ||||
|      */ | ||||
|     public function getAttestationCertificateKeyIdentifiers(): array | ||||
|     { | ||||
|         return $this->attestationCertificateKeyIdentifiers; | ||||
|     } | ||||
|  | ||||
|     public function getDescription(): string | ||||
|     { | ||||
|         return $this->description; | ||||
|     } | ||||
|  | ||||
|     public function getAlternativeDescriptions(): AlternativeDescriptions | ||||
|     { | ||||
|         return $this->alternativeDescriptions; | ||||
|     } | ||||
|  | ||||
|     public function getAuthenticatorVersion(): int | ||||
|     { | ||||
|         return $this->authenticatorVersion; | ||||
|     } | ||||
|  | ||||
|     public function getProtocolFamily(): string | ||||
|     { | ||||
|         return $this->protocolFamily; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Version[] | ||||
|      */ | ||||
|     public function getUpv(): array | ||||
|     { | ||||
|         return $this->upv; | ||||
|     } | ||||
|  | ||||
|     public function getSchema(): ?int | ||||
|     { | ||||
|         return $this->schema; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string[] | ||||
|      */ | ||||
|     public function getAuthenticationAlgorithms(): array | ||||
|     { | ||||
|         return $this->authenticationAlgorithms; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string[] | ||||
|      */ | ||||
|     public function getPublicKeyAlgAndEncodings(): array | ||||
|     { | ||||
|         return $this->publicKeyAlgAndEncodings; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string[] | ||||
|      */ | ||||
|     public function getAttestationTypes(): array | ||||
|     { | ||||
|         return $this->attestationTypes; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return VerificationMethodANDCombinations[] | ||||
|      */ | ||||
|     public function getUserVerificationDetails(): array | ||||
|     { | ||||
|         return $this->userVerificationDetails; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string[] | ||||
|      */ | ||||
|     public function getKeyProtection(): array | ||||
|     { | ||||
|         return $this->keyProtection; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string[] | ||||
|      */ | ||||
|     public function getMatcherProtection(): array | ||||
|     { | ||||
|         return $this->matcherProtection; | ||||
|     } | ||||
|  | ||||
|     public function getCryptoStrength(): ?int | ||||
|     { | ||||
|         return $this->cryptoStrength; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string[] | ||||
|      */ | ||||
|     public function getAttachmentHint(): array | ||||
|     { | ||||
|         return $this->attachmentHint; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string[] | ||||
|      */ | ||||
|     public function getTcDisplay(): array | ||||
|     { | ||||
|         return $this->tcDisplay; | ||||
|     } | ||||
|  | ||||
|     public function getTcDisplayContentType(): ?string | ||||
|     { | ||||
|         return $this->tcDisplayContentType; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return DisplayPNGCharacteristicsDescriptor[] | ||||
|      */ | ||||
|     public function getTcDisplayPNGCharacteristics(): array | ||||
|     { | ||||
|         return $this->tcDisplayPNGCharacteristics; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string[] | ||||
|      */ | ||||
|     public function getAttestationRootCertificates(): array | ||||
|     { | ||||
|         return $this->attestationRootCertificates; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return EcdaaTrustAnchor[] | ||||
|      * | ||||
|      * @deprecated since 4.2.0 and will be removed in 5.0.0. The ECDAA Trust Anchor does no longer exist in Webauthn specification. | ||||
|      */ | ||||
|     public function getEcdaaTrustAnchors(): array | ||||
|     { | ||||
|         return $this->ecdaaTrustAnchors; | ||||
|     } | ||||
|  | ||||
|     public function getIcon(): ?string | ||||
|     { | ||||
|         return $this->icon; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return ExtensionDescriptor[] | ||||
|      */ | ||||
|     public function getSupportedExtensions(): array | ||||
|     { | ||||
|         return $this->supportedExtensions; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array<string, mixed> $data | ||||
|      */ | ||||
|     public static function createFromArray(array $data): self | ||||
|     { | ||||
|         $requiredKeys = [ | ||||
|             'description', | ||||
|             'authenticatorVersion', | ||||
|             'protocolFamily', | ||||
|             'schema', | ||||
|             'upv', | ||||
|             'authenticationAlgorithms', | ||||
|             'publicKeyAlgAndEncodings', | ||||
|             'attestationTypes', | ||||
|             'userVerificationDetails', | ||||
|             'matcherProtection', | ||||
|             'tcDisplay', | ||||
|             'attestationRootCertificates', | ||||
|         ]; | ||||
|         foreach ($requiredKeys as $key) { | ||||
|             array_key_exists($key, $data) || throw MetadataStatementLoadingException::create(sprintf( | ||||
|                 'Invalid data. The key "%s" is missing', | ||||
|                 $key | ||||
|             )); | ||||
|         } | ||||
|         $subObjects = [ | ||||
|             'authenticationAlgorithms', | ||||
|             'publicKeyAlgAndEncodings', | ||||
|             'attestationTypes', | ||||
|             'matcherProtection', | ||||
|             'tcDisplay', | ||||
|             'attestationRootCertificates', | ||||
|         ]; | ||||
|         foreach ($subObjects as $subObject) { | ||||
|             is_array($data[$subObject]) || throw MetadataStatementLoadingException::create(sprintf( | ||||
|                 'Invalid Metadata Statement. The parameter "%s" shall be a list of strings.', | ||||
|                 $subObject | ||||
|             )); | ||||
|             foreach ($data[$subObject] as $datum) { | ||||
|                 is_string($datum) || throw MetadataStatementLoadingException::create(sprintf( | ||||
|                     'Invalid Metadata Statement. The parameter "%s" shall be a list of strings.', | ||||
|                     $subObject | ||||
|                 )); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $object = new self( | ||||
|             $data['description'], | ||||
|             $data['authenticatorVersion'], | ||||
|             $data['protocolFamily'], | ||||
|             $data['schema'], | ||||
|             array_map(static function ($upv): Version { | ||||
|                 is_array($upv) || throw MetadataStatementLoadingException::create('Invalid Metadata Statement'); | ||||
|  | ||||
|                 return Version::createFromArray($upv); | ||||
|             }, $data['upv']), | ||||
|             $data['authenticationAlgorithms'], | ||||
|             $data['publicKeyAlgAndEncodings'], | ||||
|             $data['attestationTypes'], | ||||
|             array_map(static function ($userVerificationDetails): VerificationMethodANDCombinations { | ||||
|                 is_array($userVerificationDetails) || throw MetadataStatementLoadingException::create( | ||||
|                     'Invalid Metadata Statement' | ||||
|                 ); | ||||
|  | ||||
|                 return VerificationMethodANDCombinations::createFromArray($userVerificationDetails); | ||||
|             }, $data['userVerificationDetails']), | ||||
|             $data['matcherProtection'], | ||||
|             $data['tcDisplay'], | ||||
|             CertificateToolbox::fixPEMStructures($data['attestationRootCertificates']) | ||||
|         ); | ||||
|  | ||||
|         $object->legalHeader = $data['legalHeader'] ?? null; | ||||
|         $object->aaid = $data['aaid'] ?? null; | ||||
|         $object->aaguid = $data['aaguid'] ?? null; | ||||
|         $object->attestationCertificateKeyIdentifiers = $data['attestationCertificateKeyIdentifiers'] ?? []; | ||||
|         $object->alternativeDescriptions = AlternativeDescriptions::create($data['alternativeDescriptions'] ?? []); | ||||
|         $object->authenticatorGetInfo = isset($data['attestationTypes']) ? AuthenticatorGetInfo::create( | ||||
|             $data['attestationTypes'] | ||||
|         ) : null; | ||||
|         $object->keyProtection = $data['keyProtection'] ?? []; | ||||
|         $object->isKeyRestricted = $data['isKeyRestricted'] ?? null; | ||||
|         $object->isFreshUserVerificationRequired = $data['isFreshUserVerificationRequired'] ?? null; | ||||
|         $object->cryptoStrength = $data['cryptoStrength'] ?? null; | ||||
|         $object->attachmentHint = $data['attachmentHint'] ?? []; | ||||
|         $object->tcDisplayContentType = $data['tcDisplayContentType'] ?? null; | ||||
|         if (isset($data['tcDisplayPNGCharacteristics'])) { | ||||
|             $tcDisplayPNGCharacteristics = $data['tcDisplayPNGCharacteristics']; | ||||
|             is_array($tcDisplayPNGCharacteristics) || throw MetadataStatementLoadingException::create( | ||||
|                 'Invalid Metadata Statement' | ||||
|             ); | ||||
|             foreach ($tcDisplayPNGCharacteristics as $tcDisplayPNGCharacteristic) { | ||||
|                 is_array($tcDisplayPNGCharacteristic) || throw MetadataStatementLoadingException::create( | ||||
|                     'Invalid Metadata Statement' | ||||
|                 ); | ||||
|                 $object->tcDisplayPNGCharacteristics[] = DisplayPNGCharacteristicsDescriptor::createFromArray( | ||||
|                     $tcDisplayPNGCharacteristic | ||||
|                 ); | ||||
|             } | ||||
|         } | ||||
|         $object->ecdaaTrustAnchors = $data['ecdaaTrustAnchors'] ?? []; | ||||
|         $object->icon = $data['icon'] ?? null; | ||||
|         if (isset($data['supportedExtensions'])) { | ||||
|             $supportedExtensions = $data['supportedExtensions']; | ||||
|             is_array($supportedExtensions) || throw MetadataStatementLoadingException::create( | ||||
|                 'Invalid Metadata Statement' | ||||
|             ); | ||||
|             foreach ($supportedExtensions as $supportedExtension) { | ||||
|                 is_array($supportedExtension) || throw MetadataStatementLoadingException::create( | ||||
|                     'Invalid Metadata Statement' | ||||
|                 ); | ||||
|                 $object->supportedExtensions[] = ExtensionDescriptor::createFromArray($supportedExtension); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $object; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array<string, mixed> | ||||
|      */ | ||||
|     public function jsonSerialize(): array | ||||
|     { | ||||
|         $data = [ | ||||
|             'legalHeader' => $this->legalHeader, | ||||
|             'aaid' => $this->aaid, | ||||
|             'aaguid' => $this->aaguid, | ||||
|             'attestationCertificateKeyIdentifiers' => $this->attestationCertificateKeyIdentifiers, | ||||
|             'description' => $this->description, | ||||
|             'alternativeDescriptions' => $this->alternativeDescriptions, | ||||
|             'authenticatorVersion' => $this->authenticatorVersion, | ||||
|             'protocolFamily' => $this->protocolFamily, | ||||
|             'upv' => $this->upv, | ||||
|             'authenticationAlgorithms' => $this->authenticationAlgorithms, | ||||
|             'publicKeyAlgAndEncodings' => $this->publicKeyAlgAndEncodings, | ||||
|             'attestationTypes' => $this->attestationTypes, | ||||
|             'userVerificationDetails' => $this->userVerificationDetails, | ||||
|             'keyProtection' => $this->keyProtection, | ||||
|             'isKeyRestricted' => $this->isKeyRestricted, | ||||
|             'isFreshUserVerificationRequired' => $this->isFreshUserVerificationRequired, | ||||
|             'matcherProtection' => $this->matcherProtection, | ||||
|             'cryptoStrength' => $this->cryptoStrength, | ||||
|             'attachmentHint' => $this->attachmentHint, | ||||
|             'tcDisplay' => $this->tcDisplay, | ||||
|             'tcDisplayContentType' => $this->tcDisplayContentType, | ||||
|             'tcDisplayPNGCharacteristics' => array_map( | ||||
|                 static fn (DisplayPNGCharacteristicsDescriptor $object): array => $object->jsonSerialize(), | ||||
|                 $this->tcDisplayPNGCharacteristics | ||||
|             ), | ||||
|             'attestationRootCertificates' => CertificateToolbox::fixPEMStructures($this->attestationRootCertificates), | ||||
|             'ecdaaTrustAnchors' => array_map( | ||||
|                 static fn (EcdaaTrustAnchor $object): array => $object->jsonSerialize(), | ||||
|                 $this->ecdaaTrustAnchors | ||||
|             ), | ||||
|             'icon' => $this->icon, | ||||
|             'authenticatorGetInfo' => $this->authenticatorGetInfo, | ||||
|             'supportedExtensions' => array_map( | ||||
|                 static fn (ExtensionDescriptor $object): array => $object->jsonSerialize(), | ||||
|                 $this->supportedExtensions | ||||
|             ), | ||||
|         ]; | ||||
|  | ||||
|         return Utils::filterNullValues($data); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										66
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/PatternAccuracyDescriptor.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/PatternAccuracyDescriptor.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,66 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Statement; | ||||
|  | ||||
| use function array_key_exists; | ||||
| use function is_int; | ||||
| use Webauthn\MetadataService\Exception\MetadataStatementLoadingException; | ||||
| use Webauthn\MetadataService\Utils; | ||||
|  | ||||
| /** | ||||
|  * @final | ||||
|  */ | ||||
| class PatternAccuracyDescriptor extends AbstractDescriptor | ||||
| { | ||||
|     private readonly int $minComplexity; | ||||
|  | ||||
|     public function __construct(int $minComplexity, ?int $maxRetries = null, ?int $blockSlowdown = null) | ||||
|     { | ||||
|         $minComplexity >= 0 || throw MetadataStatementLoadingException::create( | ||||
|             'Invalid data. The value of "minComplexity" must be a positive integer' | ||||
|         ); | ||||
|         $this->minComplexity = $minComplexity; | ||||
|         parent::__construct($maxRetries, $blockSlowdown); | ||||
|     } | ||||
|  | ||||
|     public function getMinComplexity(): int | ||||
|     { | ||||
|         return $this->minComplexity; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array<string, mixed> $data | ||||
|      */ | ||||
|     public static function createFromArray(array $data): self | ||||
|     { | ||||
|         $data = Utils::filterNullValues($data); | ||||
|         array_key_exists('minComplexity', $data) || throw MetadataStatementLoadingException::create( | ||||
|             'The key "minComplexity" is missing' | ||||
|         ); | ||||
|         foreach (['minComplexity', 'maxRetries', 'blockSlowdown'] as $key) { | ||||
|             if (array_key_exists($key, $data)) { | ||||
|                 is_int($data[$key]) || throw MetadataStatementLoadingException::create( | ||||
|                     sprintf('Invalid data. The value of "%s" must be a positive integer', $key) | ||||
|                 ); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return new self($data['minComplexity'], $data['maxRetries'] ?? null, $data['blockSlowdown'] ?? null); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array<string, int|null> | ||||
|      */ | ||||
|     public function jsonSerialize(): array | ||||
|     { | ||||
|         $data = [ | ||||
|             'minComplexity' => $this->minComplexity, | ||||
|             'maxRetries' => $this->getMaxRetries(), | ||||
|             'blockSlowdown' => $this->getBlockSlowdown(), | ||||
|         ]; | ||||
|  | ||||
|         return Utils::filterNullValues($data); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										77
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/RgbPaletteEntry.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/RgbPaletteEntry.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,77 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Statement; | ||||
|  | ||||
| use function array_key_exists; | ||||
| use function is_int; | ||||
| use JsonSerializable; | ||||
| use Webauthn\MetadataService\Exception\MetadataStatementLoadingException; | ||||
|  | ||||
| /** | ||||
|  * @final | ||||
|  */ | ||||
| class RgbPaletteEntry implements JsonSerializable | ||||
| { | ||||
|     private readonly int $r; | ||||
|  | ||||
|     private readonly int $g; | ||||
|  | ||||
|     private readonly int $b; | ||||
|  | ||||
|     public function __construct(int $r, int $g, int $b) | ||||
|     { | ||||
|         ($r >= 0 && $r <= 255) || throw MetadataStatementLoadingException::create('The key "r" is invalid'); | ||||
|         ($g >= 0 && $g <= 255) || throw MetadataStatementLoadingException::create('The key "g" is invalid'); | ||||
|         ($b >= 0 && $b <= 255) || throw MetadataStatementLoadingException::create('The key "b" is invalid'); | ||||
|         $this->r = $r; | ||||
|         $this->g = $g; | ||||
|         $this->b = $b; | ||||
|     } | ||||
|  | ||||
|     public function getR(): int | ||||
|     { | ||||
|         return $this->r; | ||||
|     } | ||||
|  | ||||
|     public function getG(): int | ||||
|     { | ||||
|         return $this->g; | ||||
|     } | ||||
|  | ||||
|     public function getB(): int | ||||
|     { | ||||
|         return $this->b; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array<string, mixed> $data | ||||
|      */ | ||||
|     public static function createFromArray(array $data): self | ||||
|     { | ||||
|         foreach (['r', 'g', 'b'] as $key) { | ||||
|             array_key_exists($key, $data) || throw MetadataStatementLoadingException::create(sprintf( | ||||
|                 'The key "%s" is missing', | ||||
|                 $key | ||||
|             )); | ||||
|             is_int($data[$key]) || throw MetadataStatementLoadingException::create( | ||||
|                 sprintf('The key "%s" is invalid', $key) | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         return new self($data['r'], $data['g'], $data['b']); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array<string, int> | ||||
|      */ | ||||
|     public function jsonSerialize(): array | ||||
|     { | ||||
|         return [ | ||||
|             'r' => $this->r, | ||||
|             'g' => $this->g, | ||||
|             'b' => $this->b, | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										58
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/RogueListEntry.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/RogueListEntry.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,58 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Statement; | ||||
|  | ||||
| use function array_key_exists; | ||||
| use function is_string; | ||||
| use JsonSerializable; | ||||
| use Webauthn\MetadataService\Exception\MetadataStatementLoadingException; | ||||
|  | ||||
| /** | ||||
|  * @final | ||||
|  */ | ||||
| class RogueListEntry implements JsonSerializable | ||||
| { | ||||
|     public function __construct( | ||||
|         private readonly string $sk, | ||||
|         private readonly string $date | ||||
|     ) { | ||||
|     } | ||||
|  | ||||
|     public function getSk(): string | ||||
|     { | ||||
|         return $this->sk; | ||||
|     } | ||||
|  | ||||
|     public function getDate(): ?string | ||||
|     { | ||||
|         return $this->date; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array<string, mixed> $data | ||||
|      */ | ||||
|     public static function createFromArray(array $data): self | ||||
|     { | ||||
|         array_key_exists('sk', $data) || throw MetadataStatementLoadingException::create('The key "sk" is missing'); | ||||
|         is_string($data['sk']) || throw MetadataStatementLoadingException::create('The key "date" is invalid'); | ||||
|         array_key_exists('date', $data) || throw MetadataStatementLoadingException::create( | ||||
|             'The key "date" is missing' | ||||
|         ); | ||||
|         is_string($data['date']) || throw MetadataStatementLoadingException::create('The key "date" is invalid'); | ||||
|  | ||||
|         return new self($data['sk'], $data['date']); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array<string, mixed> | ||||
|      */ | ||||
|     public function jsonSerialize(): array | ||||
|     { | ||||
|         return [ | ||||
|             'sk' => $this->sk, | ||||
|             'date' => $this->date, | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										148
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/StatusReport.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/StatusReport.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,148 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Statement; | ||||
|  | ||||
| use function array_key_exists; | ||||
| use function in_array; | ||||
| use function is_string; | ||||
| use JsonSerializable; | ||||
| use Webauthn\MetadataService\Exception\MetadataStatementLoadingException; | ||||
| use Webauthn\MetadataService\Utils; | ||||
|  | ||||
| /** | ||||
|  * @final | ||||
|  */ | ||||
| class StatusReport implements JsonSerializable | ||||
| { | ||||
|     /** | ||||
|      * @see AuthenticatorStatus | ||||
|      */ | ||||
|     private readonly string $status; | ||||
|  | ||||
|     public function __construct( | ||||
|         string $status, | ||||
|         private readonly ?string $effectiveDate, | ||||
|         private readonly ?string $certificate, | ||||
|         private readonly ?string $url, | ||||
|         private readonly ?string $certificationDescriptor, | ||||
|         private readonly ?string $certificateNumber, | ||||
|         private readonly ?string $certificationPolicyVersion, | ||||
|         private readonly ?string $certificationRequirementsVersion | ||||
|     ) { | ||||
|         in_array($status, AuthenticatorStatus::list(), true) || throw MetadataStatementLoadingException::create( | ||||
|             'The value of the key "status" is not acceptable' | ||||
|         ); | ||||
|  | ||||
|         $this->status = $status; | ||||
|     } | ||||
|  | ||||
|     public function isCompromised(): bool | ||||
|     { | ||||
|         return in_array($this->status, [ | ||||
|             AuthenticatorStatus::ATTESTATION_KEY_COMPROMISE, | ||||
|             AuthenticatorStatus::USER_KEY_PHYSICAL_COMPROMISE, | ||||
|             AuthenticatorStatus::USER_KEY_REMOTE_COMPROMISE, | ||||
|             AuthenticatorStatus::USER_VERIFICATION_BYPASS, | ||||
|         ], true); | ||||
|     } | ||||
|  | ||||
|     public function getStatus(): string | ||||
|     { | ||||
|         return $this->status; | ||||
|     } | ||||
|  | ||||
|     public function getEffectiveDate(): ?string | ||||
|     { | ||||
|         return $this->effectiveDate; | ||||
|     } | ||||
|  | ||||
|     public function getCertificate(): ?string | ||||
|     { | ||||
|         return $this->certificate; | ||||
|     } | ||||
|  | ||||
|     public function getUrl(): ?string | ||||
|     { | ||||
|         return $this->url; | ||||
|     } | ||||
|  | ||||
|     public function getCertificationDescriptor(): ?string | ||||
|     { | ||||
|         return $this->certificationDescriptor; | ||||
|     } | ||||
|  | ||||
|     public function getCertificateNumber(): ?string | ||||
|     { | ||||
|         return $this->certificateNumber; | ||||
|     } | ||||
|  | ||||
|     public function getCertificationPolicyVersion(): ?string | ||||
|     { | ||||
|         return $this->certificationPolicyVersion; | ||||
|     } | ||||
|  | ||||
|     public function getCertificationRequirementsVersion(): ?string | ||||
|     { | ||||
|         return $this->certificationRequirementsVersion; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array<string, mixed> $data | ||||
|      */ | ||||
|     public static function createFromArray(array $data): self | ||||
|     { | ||||
|         $data = Utils::filterNullValues($data); | ||||
|         array_key_exists('status', $data) || throw MetadataStatementLoadingException::create( | ||||
|             'The key "status" is missing' | ||||
|         ); | ||||
|         foreach ([ | ||||
|             'effectiveDate', | ||||
|             'certificate', | ||||
|             'url', | ||||
|             'certificationDescriptor', | ||||
|             'certificateNumber', | ||||
|             'certificationPolicyVersion', | ||||
|             'certificationRequirementsVersion', | ||||
|         ] as $key) { | ||||
|             if (isset($data[$key])) { | ||||
|                 $value = $data[$key]; | ||||
|                 $value === null || is_string($value) || throw MetadataStatementLoadingException::create(sprintf( | ||||
|                     'The value of the key "%s" is invalid', | ||||
|                     $key | ||||
|                 )); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return new self( | ||||
|             $data['status'], | ||||
|             $data['effectiveDate'] ?? null, | ||||
|             $data['certificate'] ?? null, | ||||
|             $data['url'] ?? null, | ||||
|             $data['certificationDescriptor'] ?? null, | ||||
|             $data['certificateNumber'] ?? null, | ||||
|             $data['certificationPolicyVersion'] ?? null, | ||||
|             $data['certificationRequirementsVersion'] ?? null | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array<string, mixed> | ||||
|      */ | ||||
|     public function jsonSerialize(): array | ||||
|     { | ||||
|         $data = [ | ||||
|             'status' => $this->status, | ||||
|             'effectiveDate' => $this->effectiveDate, | ||||
|             'certificate' => $this->certificate, | ||||
|             'url' => $this->url, | ||||
|             'certificationDescriptor' => $this->certificationDescriptor, | ||||
|             'certificateNumber' => $this->certificateNumber, | ||||
|             'certificationPolicyVersion' => $this->certificationPolicyVersion, | ||||
|             'certificationRequirementsVersion' => $this->certificationRequirementsVersion, | ||||
|         ]; | ||||
|  | ||||
|         return Utils::filterNullValues($data); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										61
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/VerificationMethodANDCombinations.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/VerificationMethodANDCombinations.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,61 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Statement; | ||||
|  | ||||
| use function is_array; | ||||
| use JsonSerializable; | ||||
| use Webauthn\MetadataService\Exception\MetadataStatementLoadingException; | ||||
|  | ||||
| /** | ||||
|  * @final | ||||
|  */ | ||||
| class VerificationMethodANDCombinations implements JsonSerializable | ||||
| { | ||||
|     /** | ||||
|      * @var VerificationMethodDescriptor[] | ||||
|      */ | ||||
|     private array $verificationMethods = []; | ||||
|  | ||||
|     public function addVerificationMethodDescriptor(VerificationMethodDescriptor $verificationMethodDescriptor): self | ||||
|     { | ||||
|         $this->verificationMethods[] = $verificationMethodDescriptor; | ||||
|  | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return VerificationMethodDescriptor[] | ||||
|      */ | ||||
|     public function getVerificationMethods(): array | ||||
|     { | ||||
|         return $this->verificationMethods; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array<string, mixed> $data | ||||
|      */ | ||||
|     public static function createFromArray(array $data): self | ||||
|     { | ||||
|         $object = new self(); | ||||
|  | ||||
|         foreach ($data as $datum) { | ||||
|             is_array($datum) || throw MetadataStatementLoadingException::create('Invalid data'); | ||||
|             $object->addVerificationMethodDescriptor(VerificationMethodDescriptor::createFromArray($datum)); | ||||
|         } | ||||
|  | ||||
|         return $object; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array<array<mixed>> | ||||
|      */ | ||||
|     public function jsonSerialize(): array | ||||
|     { | ||||
|         return array_map( | ||||
|             static fn (VerificationMethodDescriptor $object): array => $object->jsonSerialize(), | ||||
|             $this->verificationMethods | ||||
|         ); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										186
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/VerificationMethodDescriptor.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										186
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/VerificationMethodDescriptor.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,186 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Statement; | ||||
|  | ||||
| use function array_key_exists; | ||||
| use function is_array; | ||||
| use JsonSerializable; | ||||
| use Webauthn\MetadataService\Exception\MetadataStatementLoadingException; | ||||
| use Webauthn\MetadataService\Utils; | ||||
|  | ||||
| /** | ||||
|  * @final | ||||
|  */ | ||||
| class VerificationMethodDescriptor implements JsonSerializable | ||||
| { | ||||
|     final public const USER_VERIFY_PRESENCE_INTERNAL = 'presence_internal'; | ||||
|  | ||||
|     final public const USER_VERIFY_FINGERPRINT_INTERNAL = 'fingerprint_internal'; | ||||
|  | ||||
|     final public const USER_VERIFY_PASSCODE_INTERNAL = 'passcode_internal'; | ||||
|  | ||||
|     final public const USER_VERIFY_VOICEPRINT_INTERNAL = 'voiceprint_internal'; | ||||
|  | ||||
|     final public const USER_VERIFY_FACEPRINT_INTERNAL = 'faceprint_internal'; | ||||
|  | ||||
|     final public const USER_VERIFY_LOCATION_INTERNAL = 'location_internal'; | ||||
|  | ||||
|     final public const USER_VERIFY_EYEPRINT_INTERNAL = 'eyeprint_internal'; | ||||
|  | ||||
|     final public const USER_VERIFY_PATTERN_INTERNAL = 'pattern_internal'; | ||||
|  | ||||
|     final public const USER_VERIFY_HANDPRINT_INTERNAL = 'handprint_internal'; | ||||
|  | ||||
|     final public const USER_VERIFY_PASSCODE_EXTERNAL = 'passcode_external'; | ||||
|  | ||||
|     final public const USER_VERIFY_PATTERN_EXTERNAL = 'pattern_external'; | ||||
|  | ||||
|     final public const USER_VERIFY_NONE = 'none'; | ||||
|  | ||||
|     final public const USER_VERIFY_ALL = 'all'; | ||||
|  | ||||
|     private readonly string $userVerificationMethod; | ||||
|  | ||||
|     public function __construct( | ||||
|         string $userVerificationMethod, | ||||
|         private readonly ?CodeAccuracyDescriptor $caDesc = null, | ||||
|         private readonly ?BiometricAccuracyDescriptor $baDesc = null, | ||||
|         private readonly ?PatternAccuracyDescriptor $paDesc = null | ||||
|     ) { | ||||
|         $userVerificationMethod >= 0 || throw MetadataStatementLoadingException::create( | ||||
|             'The parameter "userVerificationMethod" is invalid' | ||||
|         ); | ||||
|         $this->userVerificationMethod = $userVerificationMethod; | ||||
|     } | ||||
|  | ||||
|     public function getUserVerificationMethod(): string | ||||
|     { | ||||
|         return $this->userVerificationMethod; | ||||
|     } | ||||
|  | ||||
|     public function userPresence(): bool | ||||
|     { | ||||
|         return $this->userVerificationMethod === self::USER_VERIFY_PRESENCE_INTERNAL; | ||||
|     } | ||||
|  | ||||
|     public function fingerprint(): bool | ||||
|     { | ||||
|         return $this->userVerificationMethod === self::USER_VERIFY_FINGERPRINT_INTERNAL; | ||||
|     } | ||||
|  | ||||
|     public function passcodeInternal(): bool | ||||
|     { | ||||
|         return $this->userVerificationMethod === self::USER_VERIFY_PASSCODE_INTERNAL; | ||||
|     } | ||||
|  | ||||
|     public function voicePrint(): bool | ||||
|     { | ||||
|         return $this->userVerificationMethod === self::USER_VERIFY_VOICEPRINT_INTERNAL; | ||||
|     } | ||||
|  | ||||
|     public function facePrint(): bool | ||||
|     { | ||||
|         return $this->userVerificationMethod === self::USER_VERIFY_FACEPRINT_INTERNAL; | ||||
|     } | ||||
|  | ||||
|     public function location(): bool | ||||
|     { | ||||
|         return $this->userVerificationMethod === self::USER_VERIFY_LOCATION_INTERNAL; | ||||
|     } | ||||
|  | ||||
|     public function eyePrint(): bool | ||||
|     { | ||||
|         return $this->userVerificationMethod === self::USER_VERIFY_EYEPRINT_INTERNAL; | ||||
|     } | ||||
|  | ||||
|     public function patternInternal(): bool | ||||
|     { | ||||
|         return $this->userVerificationMethod === self::USER_VERIFY_PATTERN_INTERNAL; | ||||
|     } | ||||
|  | ||||
|     public function handprint(): bool | ||||
|     { | ||||
|         return $this->userVerificationMethod === self::USER_VERIFY_HANDPRINT_INTERNAL; | ||||
|     } | ||||
|  | ||||
|     public function passcodeExternal(): bool | ||||
|     { | ||||
|         return $this->userVerificationMethod === self::USER_VERIFY_PASSCODE_EXTERNAL; | ||||
|     } | ||||
|  | ||||
|     public function patternExternal(): bool | ||||
|     { | ||||
|         return $this->userVerificationMethod === self::USER_VERIFY_PATTERN_EXTERNAL; | ||||
|     } | ||||
|  | ||||
|     public function none(): bool | ||||
|     { | ||||
|         return $this->userVerificationMethod === self::USER_VERIFY_NONE; | ||||
|     } | ||||
|  | ||||
|     public function all(): bool | ||||
|     { | ||||
|         return $this->userVerificationMethod === self::USER_VERIFY_ALL; | ||||
|     } | ||||
|  | ||||
|     public function getCaDesc(): ?CodeAccuracyDescriptor | ||||
|     { | ||||
|         return $this->caDesc; | ||||
|     } | ||||
|  | ||||
|     public function getBaDesc(): ?BiometricAccuracyDescriptor | ||||
|     { | ||||
|         return $this->baDesc; | ||||
|     } | ||||
|  | ||||
|     public function getPaDesc(): ?PatternAccuracyDescriptor | ||||
|     { | ||||
|         return $this->paDesc; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array<string, mixed> $data | ||||
|      */ | ||||
|     public static function createFromArray(array $data): self | ||||
|     { | ||||
|         $data = Utils::filterNullValues($data); | ||||
|         if (isset($data['userVerification']) && ! isset($data['userVerificationMethod'])) { | ||||
|             $data['userVerificationMethod'] = $data['userVerification']; | ||||
|             unset($data['userVerification']); | ||||
|         } | ||||
|         array_key_exists('userVerificationMethod', $data) || throw MetadataStatementLoadingException::create( | ||||
|             'The parameters "userVerificationMethod" is missing' | ||||
|         ); | ||||
|  | ||||
|         foreach (['caDesc', 'baDesc', 'paDesc'] as $key) { | ||||
|             if (isset($data[$key])) { | ||||
|                 is_array($data[$key]) || throw MetadataStatementLoadingException::create( | ||||
|                     sprintf('Invalid parameter "%s"', $key) | ||||
|                 ); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $caDesc = isset($data['caDesc']) ? CodeAccuracyDescriptor::createFromArray($data['caDesc']) : null; | ||||
|         $baDesc = isset($data['baDesc']) ? BiometricAccuracyDescriptor::createFromArray($data['baDesc']) : null; | ||||
|         $paDesc = isset($data['paDesc']) ? PatternAccuracyDescriptor::createFromArray($data['paDesc']) : null; | ||||
|  | ||||
|         return new self($data['userVerificationMethod'], $caDesc, $baDesc, $paDesc); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array<string, mixed> | ||||
|      */ | ||||
|     public function jsonSerialize(): array | ||||
|     { | ||||
|         $data = [ | ||||
|             'userVerificationMethod' => $this->userVerificationMethod, | ||||
|             'caDesc' => $this->caDesc?->jsonSerialize(), | ||||
|             'baDesc' => $this->baDesc?->jsonSerialize(), | ||||
|             'paDesc' => $this->paDesc?->jsonSerialize(), | ||||
|         ]; | ||||
|  | ||||
|         return Utils::filterNullValues($data); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										73
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/Version.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								libraries/vendor/web-auth/metadata-service/src/Statement/Version.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,73 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService\Statement; | ||||
|  | ||||
| use function array_key_exists; | ||||
| use function is_int; | ||||
| use JsonSerializable; | ||||
| use Webauthn\MetadataService\Exception\MetadataStatementLoadingException; | ||||
| use Webauthn\MetadataService\Utils; | ||||
|  | ||||
| /** | ||||
|  * @final | ||||
|  */ | ||||
| class Version implements JsonSerializable | ||||
| { | ||||
|     private readonly ?int $major; | ||||
|  | ||||
|     private readonly ?int $minor; | ||||
|  | ||||
|     public function __construct(?int $major, ?int $minor) | ||||
|     { | ||||
|         if ($major === null && $minor === null) { | ||||
|             throw MetadataStatementLoadingException::create('Invalid data. Must contain at least one item'); | ||||
|         } | ||||
|         $major >= 0 || throw MetadataStatementLoadingException::create('Invalid argument "major"'); | ||||
|         $minor >= 0 || throw MetadataStatementLoadingException::create('Invalid argument "minor"'); | ||||
|  | ||||
|         $this->major = $major; | ||||
|         $this->minor = $minor; | ||||
|     } | ||||
|  | ||||
|     public function getMajor(): ?int | ||||
|     { | ||||
|         return $this->major; | ||||
|     } | ||||
|  | ||||
|     public function getMinor(): ?int | ||||
|     { | ||||
|         return $this->minor; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array<string, mixed> $data | ||||
|      */ | ||||
|     public static function createFromArray(array $data): self | ||||
|     { | ||||
|         $data = Utils::filterNullValues($data); | ||||
|         foreach (['major', 'minor'] as $key) { | ||||
|             if (array_key_exists($key, $data)) { | ||||
|                 is_int($data[$key]) || throw MetadataStatementLoadingException::create( | ||||
|                     sprintf('Invalid value for key "%s"', $key) | ||||
|                 ); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return new self($data['major'] ?? null, $data['minor'] ?? null); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array<string, int|null> | ||||
|      */ | ||||
|     public function jsonSerialize(): array | ||||
|     { | ||||
|         $data = [ | ||||
|             'major' => $this->major, | ||||
|             'minor' => $this->minor, | ||||
|         ]; | ||||
|  | ||||
|         return Utils::filterNullValues($data); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										15
									
								
								libraries/vendor/web-auth/metadata-service/src/StatusReportRepository.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								libraries/vendor/web-auth/metadata-service/src/StatusReportRepository.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService; | ||||
|  | ||||
| use Webauthn\MetadataService\Statement\StatusReport; | ||||
|  | ||||
| interface StatusReportRepository | ||||
| { | ||||
|     /** | ||||
|      * @return StatusReport[] | ||||
|      */ | ||||
|     public function findStatusReportsByAAGUID(string $aaguid): array; | ||||
| } | ||||
							
								
								
									
										21
									
								
								libraries/vendor/web-auth/metadata-service/src/Utils.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								libraries/vendor/web-auth/metadata-service/src/Utils.php
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | ||||
| <?php | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace Webauthn\MetadataService; | ||||
|  | ||||
| /** | ||||
|  * @internal | ||||
|  */ | ||||
| abstract class Utils | ||||
| { | ||||
|     /** | ||||
|      * @param array<mixed> $data | ||||
|      * | ||||
|      * @return array<mixed> | ||||
|      */ | ||||
|     public static function filterNullValues(array $data): array | ||||
|     { | ||||
|         return array_filter($data, static fn ($var): bool => $var !== null); | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user