File manager - Edit - /home/opticamezl/www/newok/Util.tar
Back
KeyChecker.php 0000644 00000006731 15173466331 0007312 0 ustar 00 <?php declare(strict_types=1); /* * The MIT License (MIT) * * Copyright (c) 2014-2020 Spomky-Labs * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. */ namespace Jose\Component\Core\Util; use function in_array; use InvalidArgumentException; use function is_array; use Jose\Component\Core\JWK; /** * @internal */ class KeyChecker { public static function checkKeyUsage(JWK $key, string $usage): void { if ($key->has('use')) { self::checkUsage($key, $usage); } if ($key->has('key_ops')) { self::checkOperation($key, $usage); } } /** * @throws InvalidArgumentException if the key is not suitable for the selected algorithm */ public static function checkKeyAlgorithm(JWK $key, string $algorithm): void { if (!$key->has('alg')) { return; } if ($key->get('alg') !== $algorithm) { throw new InvalidArgumentException(sprintf('Key is only allowed for algorithm "%s".', $key->get('alg'))); } } /** * @throws InvalidArgumentException if the key is not suitable for the selected operation */ private static function checkOperation(JWK $key, string $usage): void { $ops = $key->get('key_ops'); if (!is_array($ops)) { throw new InvalidArgumentException('Invalid key parameter "key_ops". Should be a list of key operations'); } switch ($usage) { case 'verification': if (!in_array('verify', $ops, true)) { throw new InvalidArgumentException('Key cannot be used to verify a signature'); } break; case 'signature': if (!in_array('sign', $ops, true)) { throw new InvalidArgumentException('Key cannot be used to sign'); } break; case 'encryption': if (!in_array('encrypt', $ops, true) && !in_array('wrapKey', $ops, true) && !in_array('deriveKey', $ops, true)) { throw new InvalidArgumentException('Key cannot be used to encrypt'); } break; case 'decryption': if (!in_array('decrypt', $ops, true) && !in_array('unwrapKey', $ops, true) && !in_array('deriveBits', $ops, true)) { throw new InvalidArgumentException('Key cannot be used to decrypt'); } break; default: throw new InvalidArgumentException('Unsupported key usage.'); } } /** * @throws InvalidArgumentException if the key is not suitable for the selected operation */ private static function checkUsage(JWK $key, string $usage): void { $use = $key->get('use'); switch ($usage) { case 'verification': case 'signature': if ('sig' !== $use) { throw new InvalidArgumentException('Key cannot be used to sign or verify a signature.'); } break; case 'encryption': case 'decryption': if ('enc' !== $use) { throw new InvalidArgumentException('Key cannot be used to encrypt or decrypt.'); } break; default: throw new InvalidArgumentException('Unsupported key usage.'); } } } ECKey.php 0000644 00000027205 15173466331 0006234 0 ustar 00 <?php declare(strict_types=1); /* * The MIT License (MIT) * * Copyright (c) 2014-2020 Spomky-Labs * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. */ namespace Jose\Component\Core\Util; use Base64Url\Base64Url; use function extension_loaded; use InvalidArgumentException; use function is_array; use Jose\Component\Core\JWK; use RuntimeException; /** * @internal */ class ECKey { public static function convertToPEM(JWK $jwk): string { if ($jwk->has('d')) { return self::convertPrivateKeyToPEM($jwk); } return self::convertPublicKeyToPEM($jwk); } /** * @throws InvalidArgumentException if the curve is not supported */ public static function convertPublicKeyToPEM(JWK $jwk): string { switch ($jwk->get('crv')) { case 'P-256': $der = self::p256PublicKey(); break; case 'secp256k1': $der = self::p256KPublicKey(); break; case 'P-384': $der = self::p384PublicKey(); break; case 'P-521': $der = self::p521PublicKey(); break; default: throw new InvalidArgumentException('Unsupported curve.'); } $der .= self::getKey($jwk); $pem = '-----BEGIN PUBLIC KEY-----'.PHP_EOL; $pem .= chunk_split(base64_encode($der), 64, PHP_EOL); $pem .= '-----END PUBLIC KEY-----'.PHP_EOL; return $pem; } /** * @throws InvalidArgumentException if the curve is not supported */ public static function convertPrivateKeyToPEM(JWK $jwk): string { switch ($jwk->get('crv')) { case 'P-256': $der = self::p256PrivateKey($jwk); break; case 'secp256k1': $der = self::p256KPrivateKey($jwk); break; case 'P-384': $der = self::p384PrivateKey($jwk); break; case 'P-521': $der = self::p521PrivateKey($jwk); break; default: throw new InvalidArgumentException('Unsupported curve.'); } $der .= self::getKey($jwk); $pem = '-----BEGIN EC PRIVATE KEY-----'.PHP_EOL; $pem .= chunk_split(base64_encode($der), 64, PHP_EOL); $pem .= '-----END EC PRIVATE KEY-----'.PHP_EOL; return $pem; } /** * Creates a EC key with the given curve and additional values. * * @param string $curve The curve * @param array $values values to configure the key */ public static function createECKey(string $curve, array $values = []): JWK { $jwk = self::createECKeyUsingOpenSSL($curve); $values = array_merge($values, $jwk); return new JWK($values); } /** * @throws InvalidArgumentException if the curve is not supported */ private static function getNistCurveSize(string $curve): int { switch ($curve) { case 'P-256': case 'secp256k1': return 256; case 'P-384': return 384; case 'P-521': return 521; default: throw new InvalidArgumentException(sprintf('The curve "%s" is not supported.', $curve)); } } /** * @throws RuntimeException if the extension OpenSSL is not available * @throws RuntimeException if the key cannot be created */ private static function createECKeyUsingOpenSSL(string $curve): array { if (!extension_loaded('openssl')) { throw new RuntimeException('Please install the OpenSSL extension'); } $key = openssl_pkey_new([ 'curve_name' => self::getOpensslCurveName($curve), 'private_key_type' => OPENSSL_KEYTYPE_EC, ]); if (false === $key) { throw new RuntimeException('Unable to create the key'); } $result = openssl_pkey_export($key, $out); if (false === $result) { throw new RuntimeException('Unable to create the key'); } $res = openssl_pkey_get_private($out); if (false === $res) { throw new RuntimeException('Unable to create the key'); } $details = openssl_pkey_get_details($res); if (false === $details) { throw new InvalidArgumentException('Unable to get the key details'); } $nistCurveSize = self::getNistCurveSize($curve); return [ 'kty' => 'EC', 'crv' => $curve, 'd' => Base64Url::encode(str_pad($details['ec']['d'], (int) ceil($nistCurveSize / 8), "\0", STR_PAD_LEFT)), 'x' => Base64Url::encode(str_pad($details['ec']['x'], (int) ceil($nistCurveSize / 8), "\0", STR_PAD_LEFT)), 'y' => Base64Url::encode(str_pad($details['ec']['y'], (int) ceil($nistCurveSize / 8), "\0", STR_PAD_LEFT)), ]; } /** * @throws InvalidArgumentException if the curve is not supported */ private static function getOpensslCurveName(string $curve): string { switch ($curve) { case 'P-256': return 'prime256v1'; case 'secp256k1': return 'secp256k1'; case 'P-384': return 'secp384r1'; case 'P-521': return 'secp521r1'; default: throw new InvalidArgumentException(sprintf('The curve "%s" is not supported.', $curve)); } } private static function p256PublicKey(): string { return pack( 'H*', '3059' // SEQUENCE, length 89 .'3013' // SEQUENCE, length 19 .'0607' // OID, length 7 .'2a8648ce3d0201' // 1.2.840.10045.2.1 = EC Public Key .'0608' // OID, length 8 .'2a8648ce3d030107' // 1.2.840.10045.3.1.7 = P-256 Curve .'0342' // BIT STRING, length 66 .'00' // prepend with NUL - pubkey will follow ); } private static function p256KPublicKey(): string { return pack( 'H*', '3056' // SEQUENCE, length 86 .'3010' // SEQUENCE, length 16 .'0607' // OID, length 7 .'2a8648ce3d0201' // 1.2.840.10045.2.1 = EC Public Key .'0605' // OID, length 8 .'2B8104000A' // 1.3.132.0.10 secp256k1 .'0342' // BIT STRING, length 66 .'00' // prepend with NUL - pubkey will follow ); } private static function p384PublicKey(): string { return pack( 'H*', '3076' // SEQUENCE, length 118 .'3010' // SEQUENCE, length 16 .'0607' // OID, length 7 .'2a8648ce3d0201' // 1.2.840.10045.2.1 = EC Public Key .'0605' // OID, length 5 .'2b81040022' // 1.3.132.0.34 = P-384 Curve .'0362' // BIT STRING, length 98 .'00' // prepend with NUL - pubkey will follow ); } private static function p521PublicKey(): string { return pack( 'H*', '30819b' // SEQUENCE, length 154 .'3010' // SEQUENCE, length 16 .'0607' // OID, length 7 .'2a8648ce3d0201' // 1.2.840.10045.2.1 = EC Public Key .'0605' // OID, length 5 .'2b81040023' // 1.3.132.0.35 = P-521 Curve .'038186' // BIT STRING, length 134 .'00' // prepend with NUL - pubkey will follow ); } private static function p256PrivateKey(JWK $jwk): string { $d = unpack('H*', str_pad(Base64Url::decode($jwk->get('d')), 32, "\0", STR_PAD_LEFT)); if (!is_array($d) || !isset($d[1])) { throw new InvalidArgumentException('Unable to get the private key'); } return pack( 'H*', '3077' // SEQUENCE, length 87+length($d)=32 .'020101' // INTEGER, 1 .'0420' // OCTET STRING, length($d) = 32 .$d[1] .'a00a' // TAGGED OBJECT #0, length 10 .'0608' // OID, length 8 .'2a8648ce3d030107' // 1.3.132.0.34 = P-256 Curve .'a144' // TAGGED OBJECT #1, length 68 .'0342' // BIT STRING, length 66 .'00' // prepend with NUL - pubkey will follow ); } private static function p256KPrivateKey(JWK $jwk): string { $d = unpack('H*', str_pad(Base64Url::decode($jwk->get('d')), 32, "\0", STR_PAD_LEFT)); if (!is_array($d) || !isset($d[1])) { throw new InvalidArgumentException('Unable to get the private key'); } return pack( 'H*', '3074' // SEQUENCE, length 84+length($d)=32 .'020101' // INTEGER, 1 .'0420' // OCTET STRING, length($d) = 32 .$d[1] .'a007' // TAGGED OBJECT #0, length 7 .'0605' // OID, length 5 .'2b8104000a' // 1.3.132.0.10 secp256k1 .'a144' // TAGGED OBJECT #1, length 68 .'0342' // BIT STRING, length 66 .'00' // prepend with NUL - pubkey will follow ); } private static function p384PrivateKey(JWK $jwk): string { $d = unpack('H*', str_pad(Base64Url::decode($jwk->get('d')), 48, "\0", STR_PAD_LEFT)); if (!is_array($d) || !isset($d[1])) { throw new InvalidArgumentException('Unable to get the private key'); } return pack( 'H*', '3081a4' // SEQUENCE, length 116 + length($d)=48 .'020101' // INTEGER, 1 .'0430' // OCTET STRING, length($d) = 30 .$d[1] .'a007' // TAGGED OBJECT #0, length 7 .'0605' // OID, length 5 .'2b81040022' // 1.3.132.0.34 = P-384 Curve .'a164' // TAGGED OBJECT #1, length 100 .'0362' // BIT STRING, length 98 .'00' // prepend with NUL - pubkey will follow ); } private static function p521PrivateKey(JWK $jwk): string { $d = unpack('H*', str_pad(Base64Url::decode($jwk->get('d')), 66, "\0", STR_PAD_LEFT)); if (!is_array($d) || !isset($d[1])) { throw new InvalidArgumentException('Unable to get the private key'); } return pack( 'H*', '3081dc' // SEQUENCE, length 154 + length($d)=66 .'020101' // INTEGER, 1 .'0442' // OCTET STRING, length(d) = 66 .$d[1] .'a007' // TAGGED OBJECT #0, length 7 .'0605' // OID, length 5 .'2b81040023' // 1.3.132.0.35 = P-521 Curve .'a18189' // TAGGED OBJECT #1, length 137 .'038186' // BIT STRING, length 134 .'00' // prepend with NUL - pubkey will follow ); } private static function getKey(JWK $jwk): string { $nistCurveSize = self::getNistCurveSize($jwk->get('crv')); $length = (int) ceil($nistCurveSize / 8); return "\04" .str_pad(Base64Url::decode($jwk->get('x')), $length, "\0", STR_PAD_LEFT) .str_pad(Base64Url::decode($jwk->get('y')), $length, "\0", STR_PAD_LEFT); } } BigInteger.php 0000644 00000011055 15173466331 0007307 0 ustar 00 <?php declare(strict_types=1); /* * The MIT License (MIT) * * Copyright (c) 2014-2020 Spomky-Labs * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. */ namespace Jose\Component\Core\Util; use Brick\Math\BigInteger as BrickBigInteger; use function chr; use InvalidArgumentException; /** * @internal */ class BigInteger { /** * Holds the BigInteger's value. * * @var BrickBigInteger */ private $value; private function __construct(BrickBigInteger $value) { $this->value = $value; } /** * @return BigInteger */ public static function createFromBinaryString(string $value): self { $res = unpack('H*', $value); if (false === $res) { throw new InvalidArgumentException('Unable to convert the value'); } $data = current($res); return new self(BrickBigInteger::fromBase($data, 16)); } /** * @return BigInteger */ public static function createFromDecimal(int $value): self { return new self(BrickBigInteger::of($value)); } /** * @return BigInteger */ public static function createFromBigInteger(BrickBigInteger $value): self { return new self($value); } /** * Converts a BigInteger to a binary string. */ public function toBytes(): string { if ($this->value->isEqualTo(BrickBigInteger::zero())) { return ''; } $temp = $this->value->toBase(16); $temp = 0 !== (mb_strlen($temp, '8bit') & 1) ? '0'.$temp : $temp; $temp = hex2bin($temp); if (false === $temp) { throw new InvalidArgumentException('Unable to convert the value into bytes'); } return ltrim($temp, chr(0)); } /** * Adds two BigIntegers. * * @param BigInteger $y * * @return BigInteger */ public function add(self $y): self { $value = $this->value->plus($y->value); return new self($value); } /** * Subtracts two BigIntegers. * * @param BigInteger $y * * @return BigInteger */ public function subtract(self $y): self { $value = $this->value->minus($y->value); return new self($value); } /** * Multiplies two BigIntegers. * * @param BigInteger $x * * @return BigInteger */ public function multiply(self $x): self { $value = $this->value->multipliedBy($x->value); return new self($value); } /** * Divides two BigIntegers. * * @param BigInteger $x * * @return BigInteger */ public function divide(self $x): self { $value = $this->value->dividedBy($x->value); return new self($value); } /** * Performs modular exponentiation. * * @param BigInteger $e * @param BigInteger $n * * @return BigInteger */ public function modPow(self $e, self $n): self { $value = $this->value->modPow($e->value, $n->value); return new self($value); } /** * Performs modular exponentiation. * * @param BigInteger $d * * @return BigInteger */ public function mod(self $d): self { $value = $this->value->mod($d->value); return new self($value); } public function modInverse(BigInteger $m): BigInteger { return new self($this->value->modInverse($m->value)); } /** * Compares two numbers. * * @param BigInteger $y */ public function compare(self $y): int { return $this->value->compareTo($y->value); } /** * @param BigInteger $y */ public function equals(self $y): bool { return $this->value->isEqualTo($y->value); } /** * @param BigInteger $y * * @return BigInteger */ public static function random(self $y): self { return new self(BrickBigInteger::randomRange(0, $y->value)); } /** * @param BigInteger $y * * @return BigInteger */ public function gcd(self $y): self { return new self($this->value->gcd($y->value)); } /** * @param BigInteger $y */ public function lowerThan(self $y): bool { return $this->value->isLessThan($y->value); } public function isEven(): bool { return $this->value->isEven(); } public function get(): BrickBigInteger { return $this->value; } } JsonConverter.php 0000644 00000002614 15173466331 0010072 0 ustar 00 <?php declare(strict_types=1); /* * The MIT License (MIT) * * Copyright (c) 2014-2020 Spomky-Labs * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. */ namespace Jose\Component\Core\Util; use InvalidArgumentException; use function is_string; use RuntimeException; use Throwable; final class JsonConverter { /** * @param mixed $payload * * @throws RuntimeException if the payload cannot be encoded */ public static function encode($payload): string { try { $data = json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); if (!is_string($data)) { throw new InvalidArgumentException('Unable to encode the data'); } return $data; } catch (Throwable $throwable) { throw new RuntimeException('Invalid content.', $throwable->getCode(), $throwable); } } /** * @throws RuntimeException if the payload cannot be decoded * * @return mixed */ public static function decode(string $payload) { try { return json_decode($payload, true, 512, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); } catch (Throwable $throwable) { throw new RuntimeException('Invalid content.', $throwable->getCode(), $throwable); } } } RSAKey.php 0000644 00000021705 15173466331 0006371 0 ustar 00 <?php declare(strict_types=1); /* * The MIT License (MIT) * * Copyright (c) 2014-2020 Spomky-Labs * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. */ namespace Jose\Component\Core\Util; use function array_key_exists; use Base64Url\Base64Url; use function count; use FG\ASN1\Universal\BitString; use FG\ASN1\Universal\Integer; use FG\ASN1\Universal\NullObject; use FG\ASN1\Universal\ObjectIdentifier; use FG\ASN1\Universal\OctetString; use FG\ASN1\Universal\Sequence; use InvalidArgumentException; use function is_array; use Jose\Component\Core\JWK; use RuntimeException; /** * @internal */ class RSAKey { /** * @var Sequence */ private $sequence; /** * @var bool */ private $private; /** * @var array */ private $values; /** * @var BigInteger */ private $modulus; /** * @var int */ private $modulus_length; /** * @var BigInteger */ private $public_exponent; /** * @var null|BigInteger */ private $private_exponent; /** * @var BigInteger[] */ private $primes = []; /** * @var BigInteger[] */ private $exponents = []; /** * @var null|BigInteger */ private $coefficient; private function __construct(JWK $data) { $this->values = $data->all(); $this->populateBigIntegers(); $this->private = array_key_exists('d', $this->values); } /** * @return RSAKey */ public static function createFromJWK(JWK $jwk): self { return new self($jwk); } public function getModulus(): BigInteger { return $this->modulus; } public function getModulusLength(): int { return $this->modulus_length; } public function getExponent(): BigInteger { $d = $this->getPrivateExponent(); if (null !== $d) { return $d; } return $this->getPublicExponent(); } public function getPublicExponent(): BigInteger { return $this->public_exponent; } public function getPrivateExponent(): ?BigInteger { return $this->private_exponent; } /** * @return BigInteger[] */ public function getPrimes(): array { return $this->primes; } /** * @return BigInteger[] */ public function getExponents(): array { return $this->exponents; } public function getCoefficient(): ?BigInteger { return $this->coefficient; } public function isPublic(): bool { return !array_key_exists('d', $this->values); } /** * @param RSAKey $private * * @return RSAKey */ public static function toPublic(self $private): self { $data = $private->toArray(); $keys = ['p', 'd', 'q', 'dp', 'dq', 'qi']; foreach ($keys as $key) { if (array_key_exists($key, $data)) { unset($data[$key]); } } return new self(new JWK($data)); } public function toArray(): array { return $this->values; } public function toPEM(): string { if (null === $this->sequence) { $this->sequence = new Sequence(); if (array_key_exists('d', $this->values)) { $this->initPrivateKey(); } else { $this->initPublicKey(); } } $result = '-----BEGIN '.($this->private ? 'RSA PRIVATE' : 'PUBLIC').' KEY-----'.PHP_EOL; $result .= chunk_split(base64_encode($this->sequence->getBinary()), 64, PHP_EOL); $result .= '-----END '.($this->private ? 'RSA PRIVATE' : 'PUBLIC').' KEY-----'.PHP_EOL; return $result; } /** * Exponentiate with or without Chinese Remainder Theorem. * Operation with primes 'p' and 'q' is appox. 2x faster. * * @param RSAKey $key * * @throws RuntimeException if the exponentiation cannot be achieved */ public static function exponentiate(self $key, BigInteger $c): BigInteger { if ($c->compare(BigInteger::createFromDecimal(0)) < 0 || $c->compare($key->getModulus()) > 0) { throw new RuntimeException(); } if ($key->isPublic() || null === $key->getCoefficient() || 0 === count($key->getPrimes()) || 0 === count($key->getExponents())) { return $c->modPow($key->getExponent(), $key->getModulus()); } $p = $key->getPrimes()[0]; $q = $key->getPrimes()[1]; $dP = $key->getExponents()[0]; $dQ = $key->getExponents()[1]; $qInv = $key->getCoefficient(); $m1 = $c->modPow($dP, $p); $m2 = $c->modPow($dQ, $q); $h = $qInv->multiply($m1->subtract($m2)->add($p))->mod($p); return $m2->add($h->multiply($q)); } private function populateBigIntegers(): void { $this->modulus = $this->convertBase64StringToBigInteger($this->values['n']); $this->modulus_length = mb_strlen($this->getModulus()->toBytes(), '8bit'); $this->public_exponent = $this->convertBase64StringToBigInteger($this->values['e']); if (!$this->isPublic()) { $this->private_exponent = $this->convertBase64StringToBigInteger($this->values['d']); if (array_key_exists('p', $this->values) && array_key_exists('q', $this->values)) { $this->primes = [ $this->convertBase64StringToBigInteger($this->values['p']), $this->convertBase64StringToBigInteger($this->values['q']), ]; if (array_key_exists('dp', $this->values) && array_key_exists('dq', $this->values) && array_key_exists('qi', $this->values)) { $this->exponents = [ $this->convertBase64StringToBigInteger($this->values['dp']), $this->convertBase64StringToBigInteger($this->values['dq']), ]; $this->coefficient = $this->convertBase64StringToBigInteger($this->values['qi']); } } } } private function convertBase64StringToBigInteger(string $value): BigInteger { return BigInteger::createFromBinaryString(Base64Url::decode($value)); } private function initPublicKey(): void { $oid_sequence = new Sequence(); $oid_sequence->addChild(new ObjectIdentifier('1.2.840.113549.1.1.1')); $oid_sequence->addChild(new NullObject()); $this->sequence->addChild($oid_sequence); $n = new Integer($this->fromBase64ToInteger($this->values['n'])); $e = new Integer($this->fromBase64ToInteger($this->values['e'])); $key_sequence = new Sequence(); $key_sequence->addChild($n); $key_sequence->addChild($e); $key_bit_string = new BitString(bin2hex($key_sequence->getBinary())); $this->sequence->addChild($key_bit_string); } private function initPrivateKey(): void { $this->sequence->addChild(new Integer(0)); $oid_sequence = new Sequence(); $oid_sequence->addChild(new ObjectIdentifier('1.2.840.113549.1.1.1')); $oid_sequence->addChild(new NullObject()); $this->sequence->addChild($oid_sequence); $v = new Integer(0); $n = new Integer($this->fromBase64ToInteger($this->values['n'])); $e = new Integer($this->fromBase64ToInteger($this->values['e'])); $d = new Integer($this->fromBase64ToInteger($this->values['d'])); $p = new Integer($this->fromBase64ToInteger($this->values['p'])); $q = new Integer($this->fromBase64ToInteger($this->values['q'])); $dp = array_key_exists('dp', $this->values) ? new Integer($this->fromBase64ToInteger($this->values['dp'])) : new Integer(0); $dq = array_key_exists('dq', $this->values) ? new Integer($this->fromBase64ToInteger($this->values['dq'])) : new Integer(0); $qi = array_key_exists('qi', $this->values) ? new Integer($this->fromBase64ToInteger($this->values['qi'])) : new Integer(0); $key_sequence = new Sequence(); $key_sequence->addChild($v); $key_sequence->addChild($n); $key_sequence->addChild($e); $key_sequence->addChild($d); $key_sequence->addChild($p); $key_sequence->addChild($q); $key_sequence->addChild($dp); $key_sequence->addChild($dq); $key_sequence->addChild($qi); $key_octet_string = new OctetString(bin2hex($key_sequence->getBinary())); $this->sequence->addChild($key_octet_string); } /** * @param string $value * * @return string */ private function fromBase64ToInteger($value) { $unpacked = unpack('H*', Base64Url::decode($value)); if (!is_array($unpacked) || 0 === count($unpacked)) { throw new InvalidArgumentException('Unable to get the private key'); } return \Brick\Math\BigInteger::fromBase(current($unpacked), 16)->toBase(10); } } Hash.php 0000644 00000003575 15173466331 0006163 0 ustar 00 <?php declare(strict_types=1); /* * The MIT License (MIT) * * Copyright (c) 2014-2020 Spomky-Labs * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. */ namespace Jose\Component\Core\Util; /** * @internal */ class Hash { /** * Hash Parameter. * * @var string */ private $hash; /** * DER encoding T. * * @var string */ private $t; /** * Hash Length. * * @var int */ private $length; private function __construct(string $hash, int $length, string $t) { $this->hash = $hash; $this->length = $length; $this->t = $t; } /** * @return Hash */ public static function sha1(): self { return new self('sha1', 20, "\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14"); } /** * @return Hash */ public static function sha256(): self { return new self('sha256', 32, "\x30\x31\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01\x05\x00\x04\x20"); } /** * @return Hash */ public static function sha384(): self { return new self('sha384', 48, "\x30\x41\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02\x05\x00\x04\x30"); } /** * @return Hash */ public static function sha512(): self { return new self('sha512', 64, "\x30\x51\x30\x0d\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03\x05\x00\x04\x40"); } public function getLength(): int { return $this->length; } /** * Compute the HMAC. */ public function hash(string $text): string { return hash($this->hash, $text, true); } public function name(): string { return $this->hash; } public function t(): string { return $this->t; } } ECSignature.php 0000644 00000011212 15173466331 0007434 0 ustar 00 <?php declare(strict_types=1); /* * The MIT License (MIT) * * Copyright (c) 2014-2020 Spomky-Labs * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. */ namespace Jose\Component\Core\Util; use InvalidArgumentException; use function is_string; use const STR_PAD_LEFT; /** * @internal */ final class ECSignature { private const ASN1_SEQUENCE = '30'; private const ASN1_INTEGER = '02'; private const ASN1_MAX_SINGLE_BYTE = 128; private const ASN1_LENGTH_2BYTES = '81'; private const ASN1_BIG_INTEGER_LIMIT = '7f'; private const ASN1_NEGATIVE_INTEGER = '00'; private const BYTE_SIZE = 2; /** * @throws InvalidArgumentException if the length of the signature is invalid */ public static function toAsn1(string $signature, int $length): string { $signature = bin2hex($signature); if (self::octetLength($signature) !== $length) { throw new InvalidArgumentException('Invalid signature length.'); } $pointR = self::preparePositiveInteger(mb_substr($signature, 0, $length, '8bit')); $pointS = self::preparePositiveInteger(mb_substr($signature, $length, null, '8bit')); $lengthR = self::octetLength($pointR); $lengthS = self::octetLength($pointS); $totalLength = $lengthR + $lengthS + self::BYTE_SIZE + self::BYTE_SIZE; $lengthPrefix = $totalLength > self::ASN1_MAX_SINGLE_BYTE ? self::ASN1_LENGTH_2BYTES : ''; $bin = hex2bin( self::ASN1_SEQUENCE .$lengthPrefix.dechex($totalLength) .self::ASN1_INTEGER.dechex($lengthR).$pointR .self::ASN1_INTEGER.dechex($lengthS).$pointS ); if (!is_string($bin)) { throw new InvalidArgumentException('Unable to parse the data'); } return $bin; } /** * @throws InvalidArgumentException if the signature is not an ASN.1 sequence */ public static function fromAsn1(string $signature, int $length): string { $message = bin2hex($signature); $position = 0; if (self::ASN1_SEQUENCE !== self::readAsn1Content($message, $position, self::BYTE_SIZE)) { throw new InvalidArgumentException('Invalid data. Should start with a sequence.'); } if (self::ASN1_LENGTH_2BYTES === self::readAsn1Content($message, $position, self::BYTE_SIZE)) { $position += self::BYTE_SIZE; } $pointR = self::retrievePositiveInteger(self::readAsn1Integer($message, $position)); $pointS = self::retrievePositiveInteger(self::readAsn1Integer($message, $position)); $bin = hex2bin(str_pad($pointR, $length, '0', STR_PAD_LEFT).str_pad($pointS, $length, '0', STR_PAD_LEFT)); if (!is_string($bin)) { throw new InvalidArgumentException('Unable to parse the data'); } return $bin; } private static function octetLength(string $data): int { return (int) (mb_strlen($data, '8bit') / self::BYTE_SIZE); } private static function preparePositiveInteger(string $data): string { if (mb_substr($data, 0, self::BYTE_SIZE, '8bit') > self::ASN1_BIG_INTEGER_LIMIT) { return self::ASN1_NEGATIVE_INTEGER.$data; } while (0 === mb_strpos($data, self::ASN1_NEGATIVE_INTEGER, 0, '8bit') && mb_substr($data, 2, self::BYTE_SIZE, '8bit') <= self::ASN1_BIG_INTEGER_LIMIT) { $data = mb_substr($data, 2, null, '8bit'); } return $data; } private static function readAsn1Content(string $message, int &$position, int $length): string { $content = mb_substr($message, $position, $length, '8bit'); $position += $length; return $content; } /** * @throws InvalidArgumentException if the data is not an integer */ private static function readAsn1Integer(string $message, int &$position): string { if (self::ASN1_INTEGER !== self::readAsn1Content($message, $position, self::BYTE_SIZE)) { throw new InvalidArgumentException('Invalid data. Should contain an integer.'); } $length = (int) hexdec(self::readAsn1Content($message, $position, self::BYTE_SIZE)); return self::readAsn1Content($message, $position, $length * self::BYTE_SIZE); } private static function retrievePositiveInteger(string $data): string { while (0 === mb_strpos($data, self::ASN1_NEGATIVE_INTEGER, 0, '8bit') && mb_substr($data, 2, self::BYTE_SIZE, '8bit') > self::ASN1_BIG_INTEGER_LIMIT) { $data = mb_substr($data, 2, null, '8bit'); } return $data; } }
| ver. 1.4 |
Github
|
.
| PHP 8.3.23 | Generation time: 0 |
proxy
|
phpinfo
|
Settings