AutorÃa | Ultima modificación | Ver Log |
<?php// phpcs:ignoreFilenamespace Firebase\JWT;use DomainException;use InvalidArgumentException;use UnexpectedValueException;/*** JSON Web Key implementation, based on this spec:* https://tools.ietf.org/html/draft-ietf-jose-json-web-key-41** PHP version 5** @category Authentication* @package Authentication_JWT* @author Bui Sy Nguyen <nguyenbs@gmail.com>* @license http://opensource.org/licenses/BSD-3-Clause 3-clause BSD* @link https://github.com/firebase/php-jwt*/class JWK{/*** Parse a set of JWK keys** @param array $jwks The JSON Web Key Set as an associative array** @return array An associative array that represents the set of keys** @throws InvalidArgumentException Provided JWK Set is empty* @throws UnexpectedValueException Provided JWK Set was invalid* @throws DomainException OpenSSL failure** @uses parseKey*/public static function parseKeySet(array $jwks){$keys = array();if (!isset($jwks['keys'])) {throw new UnexpectedValueException('"keys" member must exist in the JWK Set');}if (empty($jwks['keys'])) {throw new InvalidArgumentException('JWK Set did not contain any keys');}foreach ($jwks['keys'] as $k => $v) {$kid = isset($v['kid']) ? $v['kid'] : $k;if ($key = self::parseKey($v)) {$keys[$kid] = $key;}}if (0 === \count($keys)) {throw new UnexpectedValueException('No supported algorithms found in JWK Set');}return $keys;}/*** Parse a JWK key** @param array $jwk An individual JWK** @return resource|array An associative array that represents the key** @throws InvalidArgumentException Provided JWK is empty* @throws UnexpectedValueException Provided JWK was invalid* @throws DomainException OpenSSL failure** @uses createPemFromModulusAndExponent*/public static function parseKey(array $jwk){if (empty($jwk)) {throw new InvalidArgumentException('JWK must not be empty');}if (!isset($jwk['kty'])) {throw new UnexpectedValueException('JWK must contain a "kty" parameter');}switch ($jwk['kty']) {case 'RSA':if (!empty($jwk['d'])) {throw new UnexpectedValueException('RSA private keys are not supported');}if (!isset($jwk['n']) || !isset($jwk['e'])) {throw new UnexpectedValueException('RSA keys must contain values for both "n" and "e"');}$pem = self::createPemFromModulusAndExponent($jwk['n'], $jwk['e']);$publicKey = \openssl_pkey_get_public($pem);if (false === $publicKey) {throw new DomainException('OpenSSL error: ' . \openssl_error_string());}return $publicKey;default:// Currently only RSA is supportedbreak;}}/*** Create a public key represented in PEM format from RSA modulus and exponent information** @param string $n The RSA modulus encoded in Base64* @param string $e The RSA exponent encoded in Base64** @return string The RSA public key represented in PEM format** @uses encodeLength*/private static function createPemFromModulusAndExponent($n, $e){$modulus = JWT::urlsafeB64Decode($n);$publicExponent = JWT::urlsafeB64Decode($e);$components = array('modulus' => \pack('Ca*a*', 2, self::encodeLength(\strlen($modulus)), $modulus),'publicExponent' => \pack('Ca*a*', 2, self::encodeLength(\strlen($publicExponent)), $publicExponent));$rsaPublicKey = \pack('Ca*a*a*',48,self::encodeLength(\strlen($components['modulus']) + \strlen($components['publicExponent'])),$components['modulus'],$components['publicExponent']);// sequence(oid(1.2.840.113549.1.1.1), null)) = rsaEncryption.$rsaOID = \pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA$rsaPublicKey = \chr(0) . $rsaPublicKey;$rsaPublicKey = \chr(3) . self::encodeLength(\strlen($rsaPublicKey)) . $rsaPublicKey;$rsaPublicKey = \pack('Ca*a*',48,self::encodeLength(\strlen($rsaOID . $rsaPublicKey)),$rsaOID . $rsaPublicKey);$rsaPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" .\chunk_split(\base64_encode($rsaPublicKey), 64) .'-----END PUBLIC KEY-----';return $rsaPublicKey;}/*** DER-encode the length** DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See* {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.** @param int $length* @return string*/private static function encodeLength($length){if ($length <= 0x7F) {return \chr($length);}$temp = \ltrim(\pack('N', $length), \chr(0));return \pack('Ca*', 0x80 | \strlen($temp), $temp);}}