Skip to content
This repository has been archived by the owner on Jan 3, 2024. It is now read-only.

Changed version phpseclib 3 #42

Open
darkdim opened this issue Jan 20, 2021 · 9 comments
Open

Changed version phpseclib 3 #42

darkdim opened this issue Jan 20, 2021 · 9 comments

Comments

@darkdim
Copy link

darkdim commented Jan 20, 2021

Error: Class 'phpseclib\Crypt\RSA' not found in JOSE_JWK->toKey() (line 23 of \vendor\gree\jose\src\JOSE\JWK.php).

@darkdim
Copy link
Author

darkdim commented Jan 20, 2021

"require": {
"php": ">=5.6",
"phpseclib/phpseclib": ">=2.0.0"
},
in new ver phpseclib used NS as phpseclib3
need to limit ver phpseclib

@benjy
Copy link

benjy commented Feb 2, 2021

As a temporary workaround you can do that in your own project with

composer require phpseclib/phpseclib:^2.0

@terrafrost
Copy link

terrafrost commented Feb 2, 2021

composer require phpseclib/phpseclib2_compat:~1.0 should also work. That'd let you use the phpseclib v2 API with phpseclib v3

@nextofblake
Copy link

Limiting the version to v2

composer require phpseclib/phpseclib:~2.0

Also phpseclib2_compat did not work for me

$rsa = new RSA();
$rsa->_convertPublicKey($n, $e) // method not found

@terrafrost
Copy link

@nextofblake - the presence of the underscore means that that method is not an officially supported method. This can be traced back to the old PEAR coding standards. Quoting them, "Private class members are preceded by a single underscore".

phpseclib 3 doesn't follow this convention but phpseclib 1/2 did.

Anyway, I'd rewrite your code thusly:

$rsa = new RSA;
$rsa->load([
    'e' => new BigInteger('...'),
    'n' => new BigInteger('...')
]);

phpseclib 2 has supported this since the initial release of 2.0 (2.0.0).

@nextofblake
Copy link

@terrafrost thanks for the tip however the issue is specific to this package.
inspect jose-php/src/JOSE/JWK.php

function toKey() {
... stuff
$pem_string = $rsa->_convertPublicKey($n, $e);
}

@kmuenkel
Copy link

kmuenkel commented Sep 8, 2021

I wrote an override class that addresses most of not all the compatibility issues. Note that it depends on Firebase\JWT to facilitate what RSA::_convertPublicKey() previously offered. And that some Reflection hackery was needed to regain access to now-protected properties.

<?php

namespace App\Overrides\JOSE;

use Error;
use JOSE_JWK;
use ReflectionClass;
use JOSE_URLSafeBase64;
use ReflectionException;
use phpseclib3\Crypt\RSA;
use UnexpectedValueException;
use phpseclib3\Crypt\RSA\PublicKey;
use Firebase\JWT\JWK as FirebaseJWK;
use phpseclib3\Crypt\PublicKeyLoader;
use JOSE_Exception_UnexpectedAlgorithm;

/**
 * Override to cope with changes from phpseclib/phpseclib v2 to 3
 */
class JWK extends JOSE_JWK
{
    /**
     * @inheritDoc
     * @throws ReflectionException
     */
    public static function encode($key, $extra_components = [])
    {
        try {
            return parent::encode($key, $extra_components);
        } catch (JOSE_Exception_UnexpectedAlgorithm $error) {
            //
        }

        if ($key instanceof RSA\PublicKey) {
            $modulus = static::getProtectedProperty($key, 'modulus');
            $exponent = static::getProtectedProperty($key, 'exponent');

            $components = [
                'kty' => 'RSA',
                'e' => JOSE_URLSafeBase64::encode($key->publicExponent->toBytes()),
                'n' => JOSE_URLSafeBase64::encode($modulus->toBytes())
            ];

            if ($exponent != $key->publicExponent) {
                $components = array_merge($components, ['d' => JOSE_URLSafeBase64::encode($exponent->toBytes())]);
            }

            return new static(array_merge($components, $extra_components));
        }

        throw new JOSE_Exception_UnexpectedAlgorithm('Unknown key type: '.get_class($key));
    }

    /**
     * @param object $object
     * @param string $propertyName
     * @return mixed
     * @throws ReflectionException
     */
    protected static function getProtectedProperty(object $object, string $propertyName)
    {
        $reflectionClass = app(ReflectionClass::class, ['argument' => $object]);
        $reflectionProperty = $reflectionClass->getProperty($propertyName);

        if ($reflectionProperty->isPublic()) {
            throw new UnexpectedValueException($reflectionClass->name."::$propertyName is public");
        }

        $reflectionProperty->setAccessible(true);

        return $reflectionProperty->getValue($object);
    }

    /**
     * @inheritDoc
     */
    public static function decode($components)
    {
        $jwk = new static($components);

        return $jwk->toKey();
    }

    /**
     * @inheritDoc
     */
    public function toKey()
    {
        try {
            return parent::toKey();
        } catch (Error $e) {
            //
        }

        switch ($this->components['kty']) {
            case 'RSA':
                $pemResource = FirebaseJWK::parseKey($this->components);
                $keyData = openssl_pkey_get_details($pemResource);
                $keyString = $keyData['key'];

                /** @var PublicKey $rsa */
                $rsa = PublicKeyLoader::loadPublicKey($keyString);

                return $rsa;
            default:
                throw new JOSE_Exception_UnexpectedAlgorithm('Unknown key type');
        }
    }
}

@Hailong
Copy link

Hailong commented Jun 17, 2022

Here is my PR to change to phpseclib 3, #45

@ilazaridis
Copy link

@nov any chance to merge the PR above and release a new version ?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants