[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 <?php 2 3 declare(strict_types=1); 4 5 /* 6 * The MIT License (MIT) 7 * 8 * Copyright (c) 2014-2019 Spomky-Labs 9 * 10 * This software may be modified and distributed under the terms 11 * of the MIT license. See the LICENSE file for details. 12 */ 13 14 namespace Webauthn; 15 16 use Assert\Assertion; 17 use Base64Url\Base64Url; 18 use CBOR\Decoder; 19 use CBOR\MapObject; 20 use CBOR\OtherObject\OtherObjectManager; 21 use CBOR\Tag\TagObjectManager; 22 use InvalidArgumentException; 23 use Ramsey\Uuid\Uuid; 24 use Webauthn\AttestationStatement\AttestationObjectLoader; 25 use Webauthn\AuthenticationExtensions\AuthenticationExtensionsClientOutputsLoader; 26 27 class PublicKeyCredentialLoader 28 { 29 private const FLAG_AT = 0b01000000; 30 private const FLAG_ED = 0b10000000; 31 32 /** 33 * @var AttestationObjectLoader 34 */ 35 private $attestationObjectLoader; 36 37 /** 38 * @var Decoder 39 */ 40 private $decoder; 41 42 public function __construct(AttestationObjectLoader $attestationObjectLoader, ?Decoder $decoder = null) 43 { 44 if (null !== $decoder) { 45 @trigger_error('The argument "$decoder" is deprecated since 2.1 and will be removed in v3.0. Set null instead', E_USER_DEPRECATED); 46 } 47 $this->decoder = $decoder ?? new Decoder(new TagObjectManager(), new OtherObjectManager()); 48 $this->attestationObjectLoader = $attestationObjectLoader; 49 } 50 51 public function loadArray(array $json): PublicKeyCredential 52 { 53 foreach (['id', 'rawId', 'type'] as $key) { 54 Assertion::keyExists($json, $key, sprintf('The parameter "%s" is missing', $key)); 55 Assertion::string($json[$key], sprintf('The parameter "%s" shall be a string', $key)); 56 } 57 Assertion::keyExists($json, 'response', 'The parameter "response" is missing'); 58 Assertion::isArray($json['response'], 'The parameter "response" shall be an array'); 59 Assertion::eq($json['type'], 'public-key', sprintf('Unsupported type "%s"', $json['type'])); 60 61 $id = Base64Url::decode($json['id']); 62 $rawId = Base64Url::decode($json['rawId']); 63 Assertion::true(hash_equals($id, $rawId)); 64 65 $publicKeyCredential = new PublicKeyCredential( 66 $json['id'], 67 $json['type'], 68 $rawId, 69 $this->createResponse($json['response']) 70 ); 71 72 return $publicKeyCredential; 73 } 74 75 public function load(string $data): PublicKeyCredential 76 { 77 $json = json_decode($data, true); 78 Assertion::eq(JSON_ERROR_NONE, json_last_error(), 'Invalid data'); 79 80 return $this->loadArray($json); 81 } 82 83 private function createResponse(array $response): AuthenticatorResponse 84 { 85 Assertion::keyExists($response, 'clientDataJSON'); 86 switch (true) { 87 case \array_key_exists('attestationObject', $response): 88 $attestationObject = $this->attestationObjectLoader->load($response['attestationObject']); 89 90 return new AuthenticatorAttestationResponse(CollectedClientData::createFormJson($response['clientDataJSON']), $attestationObject); 91 case \array_key_exists('authenticatorData', $response) && \array_key_exists('signature', $response): 92 $authData = Base64Url::decode($response['authenticatorData']); 93 94 $authDataStream = new StringStream($authData); 95 $rp_id_hash = $authDataStream->read(32); 96 $flags = $authDataStream->read(1); 97 $signCount = $authDataStream->read(4); 98 $signCount = unpack('N', $signCount)[1]; 99 100 $attestedCredentialData = null; 101 if (0 !== (\ord($flags) & self::FLAG_AT)) { 102 $aaguid = Uuid::fromBytes($authDataStream->read(16)); 103 $credentialLength = $authDataStream->read(2); 104 $credentialLength = unpack('n', $credentialLength)[1]; 105 $credentialId = $authDataStream->read($credentialLength); 106 $credentialPublicKey = $this->decoder->decode($authDataStream); 107 Assertion::isInstanceOf($credentialPublicKey, MapObject::class, 'The data does not contain a valid credential public key.'); 108 $attestedCredentialData = new AttestedCredentialData($aaguid, $credentialId, (string) $credentialPublicKey); 109 } 110 111 $extension = null; 112 if (0 !== (\ord($flags) & self::FLAG_ED)) { 113 $extension = $this->decoder->decode($authDataStream); 114 $extension = AuthenticationExtensionsClientOutputsLoader::load($extension); 115 } 116 Assertion::true($authDataStream->isEOF(), 'Invalid authentication data. Presence of extra bytes.'); 117 $authDataStream->close(); 118 $authenticatorData = new AuthenticatorData($authData, $rp_id_hash, $flags, $signCount, $attestedCredentialData, $extension); 119 120 return new AuthenticatorAssertionResponse( 121 CollectedClientData::createFormJson($response['clientDataJSON']), 122 $authenticatorData, 123 Base64Url::decode($response['signature']), 124 $response['userHandle'] ?? null 125 ); 126 default: 127 throw new InvalidArgumentException('Unable to create the response object'); 128 } 129 } 130 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |