Oauth2-server: Encryption do not work properly

Created on 15 Nov 2016  路  7Comments  路  Source: thephpleague/oauth2-server

Using at RHEL 7.2 (Maipo).
Find a strange while testing refresh_token grant type. Server always show me decryption error:

{
  "error": "invalid_request",
  "message": "The refresh token is invalid.",
  "hint": "Cannot decrypt the refresh token"
}

Trying to investigate this issue found that decrypt function begin throw exception after some size of encoded data. It's a strange because of this data chunked for this reason properly. =\

Afterall wrote test file and run with several vps: same RHEL 7.2, ubuntu 14.04, centos 7.1. It woks properly on these machines! 8(

test.php

<?php
$private = '-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCk8k+RNDLFFCDWN1lyTRY/1qsrJAGwnTddLHnbRpP2l2T3h4ie
DteIuy4K//g63hkVqJnm6ugwfo+G/keNTHGr2vyFyTqvnNJvAsXIkciblyz+Ml/V
k5x9vu0sOp/pox6F9q9af92w+y7aB+PWTbJZsa1p/8sQr/jk7A4bXIhqzwIDAQAB
AoGANCWC8CXvcwzVAMRI2/Dw+se0H5RnkF1ztlosQB2FA62DNxo7H7UTgN+kQ8f+
wyWaCpXd6foT49jvKT9UgaBMQwVytZZh0+dACcSsLeJ5Yog+tEuYvgEOpehCrRgA
uNEeG/Jc+G3PmsCfAiiSCMh9DCn4/mHtLrbSOr2b25t7aqECQQDaQrlKSUgW4WXo
o7sIpe9u/E1K34Qh5JCwcDHYOX4KpjNBMQb0Yp7116CsGEo6wqYycnvuyIrzdDmt
Huh2RMVRAkEAwXelNzM1OMSUQbvpsh3HjezNMgTG//Z74OaBMLHnduzGmcF1QRLa
w01HxUlf1W5jukbS/vBNUdnqxOBVBaKmHwJADYZG7wh9dBWBeBn1NAL8RDdUHsic
6nC8WoKJRCnD2qsTz/1WvfwCd59l8GQM7Xk0TTn03gYFPjK8hDK/Gt0GEQJANdGJ
tURaftM4hty2UuUz2QhRwKNRlGzF4zdcIuaqhAuz55vIeXS8RG4gFAKoVSAjP/Np
yJ+icq2TQHdDT5ECcwJBAJITt5AumV+YMXRjpFcsBGR2pNCUs9uHEw6G036F9qyt
Iq+Op2P8/V55YPUXCk9nJNHv1pHgUmwELnefF3u4IgU=
-----END RSA PRIVATE KEY-----
';

$public = '-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCk8k+RNDLFFCDWN1lyTRY/1qsr
JAGwnTddLHnbRpP2l2T3h4ieDteIuy4K//g63hkVqJnm6ugwfo+G/keNTHGr2vyF
yTqvnNJvAsXIkciblyz+Ml/Vk5x9vu0sOp/pox6F9q9af92w+y7aB+PWTbJZsa1p
/8sQr/jk7A4bXIhqzwIDAQAB
-----END PUBLIC KEY-----
';

function encrypt($unencryptedData, $private)
    {
        $privateKey = openssl_pkey_get_private(
            $private, '');
        $privateKeyDetails = @openssl_pkey_get_details($privateKey);
        if ($privateKeyDetails === null) {
            throw new \LogicException(
                sprintf('Could not get details of private key: %s', $this->privateKey->getKeyPath())
            );
        }

        $chunkSize = ceil($privateKeyDetails['bits'] / 8) - 11;
        $output = '';

        while ($unencryptedData) {
            $chunk = substr($unencryptedData, 0, $chunkSize);
            $unencryptedData = substr($unencryptedData, $chunkSize);
            if (openssl_private_encrypt($chunk, $encrypted, $privateKey) === false) {
                // @codeCoverageIgnoreStart
                throw new \LogicException('Failed to encrypt data');
                // @codeCoverageIgnoreEnd
            }
            $output .= $encrypted;
        }
        openssl_pkey_free($privateKey);

        return base64_encode($output);
    }

    /**
     * Decrypt data with a public key.
     *
     * @param string $encryptedData
     *
     * @throws \LogicException
     *
     * @return string
     */
    function decrypt($encryptedData, $public)
    {
        $publicKey = openssl_pkey_get_public($public);
        $publicKeyDetails = @openssl_pkey_get_details($publicKey);
        if ($publicKeyDetails === null) {
            throw new \LogicException(
                sprintf('Could not get details of public key: %s', $this->publicKey->getKeyPath())
            );
        }

        $chunkSize = ceil($publicKeyDetails['bits'] / 8);
        $output = '';

        $encryptedData = base64_decode($encryptedData);
        //print_r($encryptedData);
        while ($encryptedData) {

            $chunk = substr($encryptedData, 0, $chunkSize);
            $encryptedData = substr($encryptedData, $chunkSize);
            if (openssl_public_decrypt($chunk, $decrypted, $publicKey/*, OPENSSL_PKCS1_OAEP_PADDING*/) === false) {
                // @codeCoverageIgnoreStart

                throw new \LogicException('Failed to decrypt data');
                // @codeCoverageIgnoreEnd
            }
            $output .= $decrypted;
        }
        openssl_pkey_free($publicKey);
//        print_r('------------');
//        print_r($output);
//        print_r('------------');
//        die();
        return $output;
    }

$data1 = json_encode(
                    [
                        'client_id'        => 'f ag dfgsdf sdf sd ',
                        'refresh_token_id' => '1111111111111dwqqdwcewe',
                        'access_token_id'  => 'jh jsbkljbklfjbnkjdbnkdgbdf',
                        'scopes'           => [],
                        'user_id'          => 123554,
                        'expire_time'      => 1290,
                    ]
                );
print_r('Encode string'."\n");
print_r($data1."\n\n");

$enc = encrypt($data1, $private);
print_r('Encoded string'."\n");
print_r($enc."\n\n");

print_r('Decoded string'."\n");
print_r(decrypt($enc, $public));

How it could be and how can i fix it?

PS: Already trying reinstall php and openssl.

Most helpful comment

@brutto it's because the encrypted string contains characters like + which have to be url-encoded. Should be base64 encoded or something to prevent that.

All 7 comments

Btw encoded string the same on test machines (as expected)

Experiencing the same problem, first few chunks can be decrypted, but last chunk fails.

Turns out it was en encoding problem for me, the Bearer token was not sent in a urlencoded form.

@PhilippSchaffrath Oh! You are right! urlencode helps to decrypt. Thanks for help!
But i still found this behaviour aliitle strange: why tokens (access/refresh) need to be urlencoded before use but not used 'as is'?

@alexbilbie Can you point about?

@brutto it's because the encrypted string contains characters like + which have to be url-encoded. Should be base64 encoded or something to prevent that.

Omg, exactly!! I supposed that encrypted token + signs already was spaces (dunno why i supposed that)! xDD

*issue closed

Please upgrade to 5.1.4 or 6.0.0 - this issue has been resolved

Was this page helpful?
0 / 5 - 0 ratings