Skip to content

Commit 10e135a

Browse files
authored
misc refactorings
1 parent c627e83 commit 10e135a

File tree

1 file changed

+83
-82
lines changed

1 file changed

+83
-82
lines changed

src/JWK.php

Lines changed: 83 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@
2020
*/
2121
class JWK
2222
{
23-
private static $oid = '1.2.840.10045.2.1';
24-
private static $asn1ObjectIdentifier = 0x06;
25-
private static $asn1Integer = 0x02; // also defined in JWT
26-
private static $asn1Sequence = 0x10; // also defined in JWT
27-
private static $asn1BitString = 0x03;
28-
private static $curves = [
23+
private const OID = '1.2.840.10045.2.1';
24+
private const ASN1_OBJECT_IDENTIFIER = 0x06;
25+
private const ASN1_INTEGER = 0x02; // also defined in JWT
26+
private const ASN1_SEQUENCE = 0x10; // also defined in JWT
27+
private const ASN1_BIT_STRING = 0x03;
28+
private const EC_CURVES = [
2929
'P-256' => '1.2.840.10045.3.1.7', // Len: 64
3030
// 'P-384' => '1.3.132.0.34', // Len: 96 (not yet supported)
3131
// 'P-521' => '1.3.132.0.35', // Len: 132 (not supported)
@@ -127,16 +127,15 @@ public static function parseKey(array $jwk): ?Key
127127
throw new UnexpectedValueException('crv not set');
128128
}
129129

130-
if (!isset(self::$curves[$jwk['crv']])) {
130+
if (!isset(self::EC_CURVES[$jwk['crv']])) {
131131
throw new DomainException('Unrecognised or unsupported EC curve');
132132
}
133133

134134
if (empty($jwk['x']) || empty($jwk['y'])) {
135135
throw new UnexpectedValueException('x and y not set');
136136
}
137137

138-
$oid = self::$curves[$jwk['crv']];
139-
$publicKey = self::ecJwkToPem($oid, $jwk['x'], $jwk['y']);
138+
$publicKey = self::createPemFromCrvAndXYCoordinates($jwk['crv'], $jwk['x'], $jwk['y']);
140139
return new Key($publicKey, $jwk['alg']);
141140
default:
142141
// Currently only RSA is supported
@@ -146,69 +145,33 @@ public static function parseKey(array $jwk): ?Key
146145
return null;
147146
}
148147

149-
/**
150-
* Encodes a string into a DER-encoded OID.
151-
*
152-
* @param string $oid the OID string
153-
* @return string the binary DER-encoded OID
154-
*/
155-
private static function encodeOID(string $oid): string
156-
{
157-
$octets = explode('.', $oid);
158-
159-
// Get the first octet
160-
$oid = chr(array_shift($octets) * 40 + array_shift($octets));
161-
162-
// Iterate over subsequent octets
163-
foreach ($octets as $octet) {
164-
if ($octet == 0) {
165-
$oid .= chr(0x00);
166-
continue;
167-
}
168-
$bin = '';
169-
170-
while ($octet) {
171-
$bin .= chr(0x80 | ($octet & 0x7f));
172-
$octet >>= 7;
173-
}
174-
$bin[0] = $bin[0] & chr(0x7f);
175-
176-
// Convert to big endian if necessary
177-
if (pack('V', 65534) == pack('L', 65534)) {
178-
$oid .= strrev($bin);
179-
} else {
180-
$oid .= $bin;
181-
}
182-
}
183-
184-
return $oid;
185-
}
186-
187148
/**
188149
* Converts the EC JWK values to pem format.
189150
*
190-
* @param string $oid the OID string
191-
* @param string $x
192-
* @return string $y
151+
* @param string $crv The EC curve (only P-256 is supported)
152+
* @param string $x The EC x-coordinate
153+
* @param string $y The EC y-coordinate
154+
*
155+
* @return string
193156
*/
194-
private static function ecJwkToPem($oid, $x, $y)
157+
private static function createPemFromCrvAndXYCoordinates(string $crv, string $x, string $y): string
195158
{
196159
$pem =
197160
self::encodeDER(
198-
self::$asn1Sequence,
161+
self::ASN1_SEQUENCE,
199162
self::encodeDER(
200-
self::$asn1Sequence,
163+
self::ASN1_SEQUENCE,
201164
self::encodeDER(
202-
self::$asn1ObjectIdentifier,
203-
self::encodeOID(self::$oid)
165+
self::ASN1_OBJECT_IDENTIFIER,
166+
self::encodeOID(self::OID)
204167
)
205168
. self::encodeDER(
206-
self::$asn1ObjectIdentifier,
207-
self::encodeOID($oid)
169+
self::ASN1_OBJECT_IDENTIFIER,
170+
self::encodeOID(self::EC_CURVES[$crv])
208171
)
209172
) .
210173
self::encodeDER(
211-
self::$asn1BitString,
174+
self::ASN1_BIT_STRING,
212175
chr(0x00) . chr(0x04)
213176
. JWT::urlsafeB64Decode($x)
214177
. JWT::urlsafeB64Decode($y)
@@ -221,30 +184,6 @@ private static function ecJwkToPem($oid, $x, $y)
221184
);
222185
}
223186

224-
/**
225-
* Encodes a value into a DER object.
226-
* Also defined in Firebase\JWT\JWT
227-
*
228-
* @param int $type DER tag
229-
* @param string $value the value to encode
230-
* @return string the encoded object
231-
*/
232-
private static function encodeDER(int $type, string $value): string
233-
{
234-
$tag_header = 0;
235-
if ($type === self::$asn1Sequence) {
236-
$tag_header |= 0x20;
237-
}
238-
239-
// Type
240-
$der = \chr($tag_header | $type);
241-
242-
// Length
243-
$der .= \chr(\strlen($value));
244-
245-
return $der . $value;
246-
}
247-
248187
/**
249188
* Create a public key represented in PEM format from RSA modulus and exponent information
250189
*
@@ -311,4 +250,66 @@ private static function encodeLength(int $length): string
311250

312251
return \pack('Ca*', 0x80 | \strlen($temp), $temp);
313252
}
253+
254+
/**
255+
* Encodes a value into a DER object.
256+
* Also defined in Firebase\JWT\JWT
257+
*
258+
* @param int $type DER tag
259+
* @param string $value the value to encode
260+
* @return string the encoded object
261+
*/
262+
private static function encodeDER(int $type, string $value): string
263+
{
264+
$tag_header = 0;
265+
if ($type === self::ASN1_SEQUENCE) {
266+
$tag_header |= 0x20;
267+
}
268+
269+
// Type
270+
$der = \chr($tag_header | $type);
271+
272+
// Length
273+
$der .= \chr(\strlen($value));
274+
275+
return $der . $value;
276+
}
277+
278+
/**
279+
* Encodes a string into a DER-encoded OID.
280+
*
281+
* @param string $oid the OID string
282+
* @return string the binary DER-encoded OID
283+
*/
284+
private static function encodeOID(string $oid): string
285+
{
286+
$octets = explode('.', $oid);
287+
288+
// Get the first octet
289+
$oid = chr(array_shift($octets) * 40 + array_shift($octets));
290+
291+
// Iterate over subsequent octets
292+
foreach ($octets as $octet) {
293+
if ($octet == 0) {
294+
$oid .= chr(0x00);
295+
continue;
296+
}
297+
$bin = '';
298+
299+
while ($octet) {
300+
$bin .= chr(0x80 | ($octet & 0x7f));
301+
$octet >>= 7;
302+
}
303+
$bin[0] = $bin[0] & chr(0x7f);
304+
305+
// Convert to big endian if necessary
306+
if (pack('V', 65534) == pack('L', 65534)) {
307+
$oid .= strrev($bin);
308+
} else {
309+
$oid .= $bin;
310+
}
311+
}
312+
313+
return $oid;
314+
}
314315
}

0 commit comments

Comments
 (0)