ILIAS  release_8 Revision v8.24
Firebase\JWT\JWK Class Reference
+ Collaboration diagram for Firebase\JWT\JWK:

Static Public Member Functions

static parseKeySet (array $jwks, string $defaultAlg=null)
 Parse a set of JWK keys. More...
 
static parseKey (array $jwk, string $defaultAlg=null)
 Parse a JWK key. More...
 

Static Private Member Functions

static createPemFromCrvAndXYCoordinates (string $crv, string $x, string $y)
 Converts the EC JWK values to pem format. More...
 
static createPemFromModulusAndExponent (string $n, string $e)
 Create a public key represented in PEM format from RSA modulus and exponent information. More...
 
static encodeLength (int $length)
 DER-encode the length. More...
 
static encodeDER (int $type, string $value)
 Encodes a value into a DER object. More...
 
static encodeOID (string $oid)
 Encodes a string into a DER-encoded OID. More...
 

Private Attributes

const OID = '1.2.840.10045.2.1'
 
const ASN1_OBJECT_IDENTIFIER = 0x06
 
const ASN1_SEQUENCE = 0x10
 
const ASN1_BIT_STRING = 0x03
 
const EC_CURVES
 
const OKP_SUBTYPES
 

Detailed Description

Definition at line 21 of file JWK.php.

Member Function Documentation

◆ createPemFromCrvAndXYCoordinates()

static Firebase\JWT\JWK::createPemFromCrvAndXYCoordinates ( string  $crv,
string  $x,
string  $y 
)
staticprivate

Converts the EC JWK values to pem format.

Parameters
string$crvThe EC curve (only P-256 & P-384 is supported)
string$xThe EC x-coordinate
string$yThe EC y-coordinate
Returns
string

Definition at line 191 of file JWK.php.

191 : string
192 {
193 $pem =
195 self::ASN1_SEQUENCE,
196 self::encodeDER(
197 self::ASN1_SEQUENCE,
198 self::encodeDER(
199 self::ASN1_OBJECT_IDENTIFIER,
200 self::encodeOID(self::OID)
201 )
202 . self::encodeDER(
203 self::ASN1_OBJECT_IDENTIFIER,
204 self::encodeOID(self::EC_CURVES[$crv])
205 )
206 ) .
207 self::encodeDER(
208 self::ASN1_BIT_STRING,
209 \chr(0x00) . \chr(0x04)
212 )
213 );
214
215 return sprintf(
216 "-----BEGIN PUBLIC KEY-----\n%s\n-----END PUBLIC KEY-----\n",
217 wordwrap(base64_encode($pem), 64, "\n", true)
218 );
219 }
static encodeDER(int $type, string $value)
Encodes a value into a DER object.
Definition: JWK.php:294
static urlsafeB64Decode(string $input)
Decode a string with URL-safe Base64.
Definition: JWT.php:412

References Firebase\JWT\JWK\encodeDER(), and Firebase\JWT\JWT\urlsafeB64Decode().

Referenced by Firebase\JWT\JWK\parseKey().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ createPemFromModulusAndExponent()

static Firebase\JWT\JWK::createPemFromModulusAndExponent ( string  $n,
string  $e 
)
staticprivate

Create a public key represented in PEM format from RSA modulus and exponent information.

Parameters
string$nThe RSA modulus encoded in Base64
string$eThe RSA exponent encoded in Base64
Returns
string The RSA public key represented in PEM format

@uses encodeLength

Definition at line 231 of file JWK.php.

234 : string {
235 $mod = JWT::urlsafeB64Decode($n);
237
238 $modulus = \pack('Ca*a*', 2, self::encodeLength(\strlen($mod)), $mod);
239 $publicExponent = \pack('Ca*a*', 2, self::encodeLength(\strlen($exp)), $exp);
240
241 $rsaPublicKey = \pack(
242 'Ca*a*a*',
243 48,
244 self::encodeLength(\strlen($modulus) + \strlen($publicExponent)),
245 $modulus,
246 $publicExponent
247 );
248
249 // sequence(oid(1.2.840.113549.1.1.1), null)) = rsaEncryption.
250 $rsaOID = \pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA
251 $rsaPublicKey = \chr(0) . $rsaPublicKey;
252 $rsaPublicKey = \chr(3) . self::encodeLength(\strlen($rsaPublicKey)) . $rsaPublicKey;
253
254 $rsaPublicKey = \pack(
255 'Ca*a*',
256 48,
257 self::encodeLength(\strlen($rsaOID . $rsaPublicKey)),
258 $rsaOID . $rsaPublicKey
259 );
260
261 return "-----BEGIN PUBLIC KEY-----\r\n" .
262 \chunk_split(\base64_encode($rsaPublicKey), 64) .
263 '-----END PUBLIC KEY-----';
264 }
static encodeLength(int $length)
DER-encode the length.
Definition: JWK.php:275

Referenced by Firebase\JWT\JWK\parseKey().

+ Here is the caller graph for this function:

◆ encodeDER()

static Firebase\JWT\JWK::encodeDER ( int  $type,
string  $value 
)
staticprivate

Encodes a value into a DER object.

Also defined in Firebase\JWT\JWT

Parameters
int$typeDER tag
string$valuethe value to encode
Returns
string the encoded object

Definition at line 294 of file JWK.php.

294 : string
295 {
296 $tag_header = 0;
297 if ($type === self::ASN1_SEQUENCE) {
298 $tag_header |= 0x20;
299 }
300
301 // Type
302 $der = \chr($tag_header | $type);
303
304 // Length
305 $der .= \chr(\strlen($value));
306
307 return $der . $value;
308 }
$type

References $type.

Referenced by Firebase\JWT\JWK\createPemFromCrvAndXYCoordinates().

+ Here is the caller graph for this function:

◆ encodeLength()

static Firebase\JWT\JWK::encodeLength ( int  $length)
staticprivate

DER-encode the length.

DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See X.690 paragraph 8.1.3 for more information.

Parameters
int$length
Returns
string

Definition at line 275 of file JWK.php.

275 : string
276 {
277 if ($length <= 0x7F) {
278 return \chr($length);
279 }
280
281 $temp = \ltrim(\pack('N', $length), \chr(0));
282
283 return \pack('Ca*', 0x80 | \strlen($temp), $temp);
284 }

◆ encodeOID()

static Firebase\JWT\JWK::encodeOID ( string  $oid)
staticprivate

Encodes a string into a DER-encoded OID.

Parameters
string$oidthe OID string
Returns
string the binary DER-encoded OID

Definition at line 316 of file JWK.php.

316 : string
317 {
318 $octets = explode('.', $oid);
319
320 // Get the first octet
321 $first = (int) array_shift($octets);
322 $second = (int) array_shift($octets);
323 $oid = \chr($first * 40 + $second);
324
325 // Iterate over subsequent octets
326 foreach ($octets as $octet) {
327 if ($octet == 0) {
328 $oid .= \chr(0x00);
329 continue;
330 }
331 $bin = '';
332
333 while ($octet) {
334 $bin .= \chr(0x80 | ($octet & 0x7f));
335 $octet >>= 7;
336 }
337 $bin[0] = $bin[0] & \chr(0x7f);
338
339 // Convert to big endian if necessary
340 if (pack('V', 65534) == pack('L', 65534)) {
341 $oid .= strrev($bin);
342 } else {
343 $oid .= $bin;
344 }
345 }
346
347 return $oid;
348 }

References ILIAS\Repository\int().

+ Here is the call graph for this function:

◆ parseKey()

static Firebase\JWT\JWK::parseKey ( array  $jwk,
string  $defaultAlg = null 
)
static

Parse a JWK key.

Parameters
array<mixed>$jwk An individual JWK
string$defaultAlgThe algorithm for the Key object if "alg" is not set in the JSON Web Key Set
Returns
Key The key object for the JWK
Exceptions
InvalidArgumentExceptionProvided JWK is empty
UnexpectedValueExceptionProvided JWK was invalid
DomainExceptionOpenSSL failure

@uses createPemFromModulusAndExponent

Definition at line 96 of file JWK.php.

96 : ?Key
97 {
98 if (empty($jwk)) {
99 throw new InvalidArgumentException('JWK must not be empty');
100 }
101
102 if (!isset($jwk['kty'])) {
103 throw new UnexpectedValueException('JWK must contain a "kty" parameter');
104 }
105
106 if (!isset($jwk['alg'])) {
107 if (\is_null($defaultAlg)) {
108 // The "alg" parameter is optional in a KTY, but an algorithm is required
109 // for parsing in this library. Use the $defaultAlg parameter when parsing the
110 // key set in order to prevent this error.
111 // @see https://datatracker.ietf.org/doc/html/rfc7517#section-4.4
112 throw new UnexpectedValueException('JWK must contain an "alg" parameter');
113 }
114 $jwk['alg'] = $defaultAlg;
115 }
116
117 switch ($jwk['kty']) {
118 case 'RSA':
119 if (!empty($jwk['d'])) {
120 throw new UnexpectedValueException('RSA private keys are not supported');
121 }
122 if (!isset($jwk['n']) || !isset($jwk['e'])) {
123 throw new UnexpectedValueException('RSA keys must contain values for both "n" and "e"');
124 }
125
126 $pem = self::createPemFromModulusAndExponent($jwk['n'], $jwk['e']);
127 $publicKey = \openssl_pkey_get_public($pem);
128 if (false === $publicKey) {
129 throw new DomainException(
130 'OpenSSL error: ' . \openssl_error_string()
131 );
132 }
133 return new Key($publicKey, $jwk['alg']);
134 case 'EC':
135 if (isset($jwk['d'])) {
136 // The key is actually a private key
137 throw new UnexpectedValueException('Key data must be for a public key');
138 }
139
140 if (empty($jwk['crv'])) {
141 throw new UnexpectedValueException('crv not set');
142 }
143
144 if (!isset(self::EC_CURVES[$jwk['crv']])) {
145 throw new DomainException('Unrecognised or unsupported EC curve');
146 }
147
148 if (empty($jwk['x']) || empty($jwk['y'])) {
149 throw new UnexpectedValueException('x and y not set');
150 }
151
152 $publicKey = self::createPemFromCrvAndXYCoordinates($jwk['crv'], $jwk['x'], $jwk['y']);
153 return new Key($publicKey, $jwk['alg']);
154 case 'OKP':
155 if (isset($jwk['d'])) {
156 // The key is actually a private key
157 throw new UnexpectedValueException('Key data must be for a public key');
158 }
159
160 if (!isset($jwk['crv'])) {
161 throw new UnexpectedValueException('crv not set');
162 }
163
164 if (empty(self::OKP_SUBTYPES[$jwk['crv']])) {
165 throw new DomainException('Unrecognised or unsupported OKP key subtype');
166 }
167
168 if (empty($jwk['x'])) {
169 throw new UnexpectedValueException('x not set');
170 }
171
172 // This library works internally with EdDSA keys (Ed25519) encoded in standard base64.
173 $publicKey = JWT::convertBase64urlToBase64($jwk['x']);
174 return new Key($publicKey, $jwk['alg']);
175 default:
176 break;
177 }
178
179 return null;
180 }
static createPemFromCrvAndXYCoordinates(string $crv, string $x, string $y)
Converts the EC JWK values to pem format.
Definition: JWK.php:191
static createPemFromModulusAndExponent(string $n, string $e)
Create a public key represented in PEM format from RSA modulus and exponent information.
Definition: JWK.php:231

References Firebase\JWT\JWK\createPemFromCrvAndXYCoordinates(), and Firebase\JWT\JWK\createPemFromModulusAndExponent().

Referenced by Firebase\JWT\CachedKeySet\offsetGet(), and ILIAS\LTI\ToolProvider\Jwt\FirebaseClient\parseKeySet().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parseKeySet()

static Firebase\JWT\JWK::parseKeySet ( array  $jwks,
string  $defaultAlg = null 
)
static

Parse a set of JWK keys.

Parameters
array<mixed>$jwks The JSON Web Key Set as an associative array
string$defaultAlgThe algorithm for the Key object if "alg" is not set in the JSON Web Key Set
Returns
array<string, Key> An associative array of key IDs (kid) to Key objects
Exceptions
InvalidArgumentExceptionProvided JWK Set is empty
UnexpectedValueExceptionProvided JWK Set was invalid
DomainExceptionOpenSSL failure

@uses parseKey

Definition at line 55 of file JWK.php.

55 : array
56 {
57 $keys = [];
58
59 if (!isset($jwks['keys'])) {
60 throw new UnexpectedValueException('"keys" member must exist in the JWK Set');
61 }
62
63 if (empty($jwks['keys'])) {
64 throw new InvalidArgumentException('JWK Set did not contain any keys');
65 }
66
67 foreach ($jwks['keys'] as $k => $v) {
68 $kid = isset($v['kid']) ? $v['kid'] : $k;
69 if ($key = self::parseKey($v, $defaultAlg)) {
70 $keys[(string) $kid] = $key;
71 }
72 }
73
74 if (0 === \count($keys)) {
75 throw new UnexpectedValueException('No supported algorithms found in JWK Set');
76 }
77
78 return $keys;
79 }
$keys
Definition: metadata.php:204
string $kid
Key ID.
Definition: System.php:88
string $key
Consumer key/client ID value.
Definition: System.php:193

References ILIAS\LTI\ToolProvider\$key, $keys, and ILIAS\LTI\ToolProvider\$kid.

Referenced by ilObjLTIConsumerGUI\saveContentSelection().

+ Here is the caller graph for this function:

Field Documentation

◆ ASN1_BIT_STRING

const Firebase\JWT\JWK::ASN1_BIT_STRING = 0x03
private

Definition at line 26 of file JWK.php.

◆ ASN1_OBJECT_IDENTIFIER

const Firebase\JWT\JWK::ASN1_OBJECT_IDENTIFIER = 0x06
private

Definition at line 24 of file JWK.php.

◆ ASN1_SEQUENCE

const Firebase\JWT\JWK::ASN1_SEQUENCE = 0x10
private

Definition at line 25 of file JWK.php.

◆ EC_CURVES

const Firebase\JWT\JWK::EC_CURVES
private
Initial value:
= [
'P-256' => '1.2.840.10045.3.1.7',
'secp256k1' => '1.3.132.0.10',
'P-384' => '1.3.132.0.34',
]

Definition at line 27 of file JWK.php.

◆ OID

const Firebase\JWT\JWK::OID = '1.2.840.10045.2.1'
private

Definition at line 23 of file JWK.php.

◆ OKP_SUBTYPES

const Firebase\JWT\JWK::OKP_SUBTYPES
private
Initial value:
= [
'Ed25519' => true,
]

Definition at line 36 of file JWK.php.


The documentation for this class was generated from the following file: