Current Path : /var/www/www-root/data/www.catalog.monolith-realty.ru/bitrix/modules/main/lib/web/ |
Current File : /var/www/www-root/data/www.catalog.monolith-realty.ru/bitrix/modules/main/lib/web/jwk.php |
<?php namespace Bitrix\Main\Web; 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 * * @package Firebase\JWT * @author Bui Sy Nguyen <nguyenbs@gmail.com> * @license http://opensource.org/licenses/BSD-3-Clause 3-clause BSD * @link https://github.com/fproject/php-jwt */ class JWK { /** * Parse a set of JWK keys * @param $source * @return array an associative array represents the set of keys */ public static function parseKeySet($source) { $keys = []; if (is_string($source)) { $source = json_decode($source, true); } else if (is_object($source)) { if (property_exists($source, 'keys')) $source = (array)$source; else $source = [$source]; } if (is_array($source)) { if (isset($source['keys'])) $source = $source['keys']; foreach ($source as $k => $v) { if (!is_string($k)) { if (is_array($v) && isset($v['kid'])) $k = $v['kid']; elseif (is_object($v) && property_exists($v, 'kid')) $k = $v->{'kid'}; } try { $v = self::parseKey($v); $keys[$k] = $v; } catch (UnexpectedValueException $e) { //Do nothing } } } if (0 < count($keys)) { return $keys; } throw new UnexpectedValueException('Failed to parse JWK'); } /** * Parse a JWK key * @param $source * @return resource|array an associative array represents the key */ public static function parseKey($source) { if (!is_array($source)) $source = (array)$source; if (!empty($source) && isset($source['kty']) && isset($source['n']) && isset($source['e'])) { switch ($source['kty']) { case 'RSA': if (array_key_exists('d', $source)) throw new UnexpectedValueException('Failed to parse JWK: RSA private key is not supported'); $pem = self::createPemFromModulusAndExponent($source['n'], $source['e']); $pKey = openssl_pkey_get_public($pem); if ($pKey !== false) return $pKey; break; default: //Currently only RSA is supported break; } } throw new UnexpectedValueException('Failed to parse JWK'); } /** * * 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 */ 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. * * @access private * @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); } }