“类名必须是有效的对象或字符串”在没有 Composer 的情况下安装 PHPSecLib

Posted

技术标签:

【中文标题】“类名必须是有效的对象或字符串”在没有 Composer 的情况下安装 PHPSecLib【英文标题】:"Class name must be a valid object or a string" When Installing PHPSecLib Without Composer 【发布时间】:2022-01-17 11:44:13 【问题描述】:

我正在尝试使用 phpSecLib 进行 RSA 加密,手动安装(即不使用 Composer)。

我正在按照我在此处找到的这些手动安装说明进行操作: https://davescripts.com/manual-installation-of-phpseclib

并尝试做我在这里找到的这个例子: How to Decrypt RSA OAEP with SHA256 using openssl on PHP

到目前为止我已经采取的步骤:

    在此处访问 GitHub 存储库:https://github.com/phpseclib/phpseclib/tree/3.0

    在“代码”下选择“下载 ZIP”。

    将文件解压到本地,并将整个 'phpseclib' 目录上传到服务器。

    创建了一个测试脚本,并对使其工作所需的多层包含和使用进行了故障排除。

    但是,目前,我遇到了一个新错误 - “类名必须是有效的对象或字符串”,我不理解并且似乎无法解决。

我的测试脚本现在如下:

<?php

  ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL);
  header("Content-Type: text/plain");
  $sIncludePath = get_include_path() . PATH_SEPARATOR . '../inc/phpseclib';
  echo $sIncludePath."\n";
  set_include_path($sIncludePath);

  include('Crypt/Common/AsymmetricKey.php');
  include('Math/BigInteger.php');
  include('Crypt/EC.php');
  include('Crypt/PublicKeyLoader.php');
  include('Crypt/RSA.php');

  use phpseclib3\Crypt\RSA;
  use phpseclib3\Crypt\PublicKeyLoader;

  function rsaEncryptionOaepSha256 ($publicKey, $plaintext) 
    $rsa = PublicKeyLoader::load($publicKey)
        ->withHash('sha256')
        ->withMGFHash('sha256');
    return $rsa->encrypt($plaintext);
  

  function rsaDecryptionOaepSha256 ($privateKey, $ciphertext) 
    $rsa = PublicKeyLoader::load($privateKey)
        ->withHash('sha256')
        ->withMGFHash('sha256');
    return $rsa->decrypt($ciphertext);
  
  
  function loadRsaPrivateKeyPem() 
    // this is a sample key - don't worry !
    return '
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDwSZYlRn86zPi9
e1RTZL7QzgE/36zjbeCMyOhf6o/WIKeVxFwVbG2FAY3YJZIxnBH+9j1XS6f+ewjG
FlJY4f2IrOpS1kPiO3fmOo5N4nc8JKvjwmKtUM0t63uFFPfs69+7mKJ4w3tk2mSN
4gb8J9P9BCXtH6Q78SdOYvdCMspA1X8eERsdLb/jjHs8+gepKqQ6+XwZbSq0vf2B
MtaAB7zTX/Dk+ZxDfwIobShPaB0mYmojE2YAQeRq1gYdwwO1dEGk6E5J2toWPpKY
/IcSYsGKyFqrsmbw0880r1BwRDer4RFrkzp4zvY+kX3eDanlyMqDLPN+ghXT1lv8
snZpbaBDAgMBAAECggEBAIVxmHzjBc11/73bPB2EGaSEg5UhdzZm0wncmZCLB453
XBqEjk8nhDsVfdzIIMSEVEowHijYz1c4pMq9osXR26eHwCp47AI73H5zjowadPVl
uEAot/xgn1IdMN/boURmSj44qiI/DcwYrTdOi2qGA+jD4PwrUl4nsxiJRZ/x7PjL
hMzRbvDxQ4/Q4ThYXwoEGiIBBK/iB3Z5eR7lFa8E5yAaxM2QP9PENBr/OqkGXLWV
qA/YTxs3gAvkUjMhlScOi7PMwRX9HsrAeLKbLuC1KJv1p2THUtZbOHqrAF/uwHaj
ygUblFaa/BTckTN7PKSVIhp7OihbD04bSRrh+nOilcECgYEA/8atV5DmNxFrxF1P
ODDjdJPNb9pzNrDF03TiFBZWS4Q+2JazyLGjZzhg5Vv9RJ7VcIjPAbMy2Cy5BUff
EFE+8ryKVWfdpPxpPYOwHCJSw4Bqqdj0Pmp/xw928ebrnUoCzdkUqYYpRWx0T7YV
RoA9RiBfQiVHhuJBSDPYJPoP34kCgYEA8H9wLE5L8raUn4NYYRuUVMa+1k4Q1N3X
Bixm5cccc/Ja4LVvrnWqmFOmfFgpVd8BcTGaPSsqfA4j/oEQp7tmjZqggVFqiM2m
J2YEv18cY/5kiDUVYR7VWSkpqVOkgiX3lK3UkIngnVMGGFnoIBlfBFF9uo02rZpC
5o5zebaDImsCgYAE9d5wv0+nq7/STBj4NwKCRUeLrsnjOqRriG3GA/TifAsX+jw8
XS2VF+PRLuqHhSkQiKazGr2Wsa9Y6d7qmxjEbmGkbGJBC+AioEYvFX9TaU8oQhvi
hgA6ZRNid58EKuZJBbe/3ek4/nR3A0oAVwZZMNGIH972P7cSZmb/uJXMOQKBgQCs
FaQAL+4sN/TUxrkAkylqF+QJmEZ26l2nrzHZjMWROYNJcsn8/XkaEhD4vGSnazCu
/B0vU6nMppmezF9Mhc112YSrw8QFK5GOc3NGNBoueqMYy1MG8Xcbm1aSMKVv8xba
rh+BZQbxy6x61CpCfaT9hAoA6HaNdeoU6y05lBz1DQKBgAbYiIk56QZHeoZKiZxy
4eicQS0sVKKRb24ZUd+04cNSTfeIuuXZrYJ48Jbr0fzjIM3EfHvLgh9rAZ+aHe/L
84Ig17KiExe+qyYHjut/SC0wODDtzM/jtrpqyYa5JoEpPIaUSgPuTH/WhO3cDsx6
3PIW4/CddNs8mCSBOqTnoaxh
-----END PRIVATE KEY-----
';
  

  function loadRsaPublicKeyPem() 
    // this is a sample key - don't worry !
    return '
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8EmWJUZ/Osz4vXtUU2S+
0M4BP9+s423gjMjoX+qP1iCnlcRcFWxthQGN2CWSMZwR/vY9V0un/nsIxhZSWOH9
iKzqUtZD4jt35jqOTeJ3PCSr48JirVDNLet7hRT37Ovfu5iieMN7ZNpkjeIG/CfT
/QQl7R+kO/EnTmL3QjLKQNV/HhEbHS2/44x7PPoHqSqkOvl8GW0qtL39gTLWgAe8
01/w5PmcQ38CKG0oT2gdJmJqIxNmAEHkatYGHcMDtXRBpOhOSdraFj6SmPyHEmLB
ishaq7Jm8NPPNK9QcEQ3q+ERa5M6eM72PpF93g2p5cjKgyzzfoIV09Zb/LJ2aW2g
QwIDAQAB
-----END PUBLIC KEY-----
';
  

  function base64Encoding ($input) 
    return base64_encode($input);
  
  function base64Decoding ($input) 
    return base64_decode($input);
  

  echo 'RSA 2048 encryption OAEP SHA-256 string' . PHP_EOL;
  $sDataToEncrypt = "The quick brown fox jumps over the lazy dog";
  echo 'plaintext: ' . $sDataToEncrypt . PHP_EOL;

  // encryption
  echo PHP_EOL . '* * * encrypt the plaintext with the RSA public key * * *' .PHP_EOL;
  $ciphertextBase64 = base64Encoding(rsaEncryptionOaepSha256(loadRsaPublicKeyPem(), $sDataToEncrypt));
  echo 'ciphertextBase64: ' . $ciphertextBase64 . PHP_EOL;

  // transport the encrypted data to recipient

  // receiving the encrypted data, decryption
  echo PHP_EOL . '* * * decrypt the ciphertext with the RSA private key * * *' .PHP_EOL;
  $ciphertextReceivedBase64 = $ciphertextBase64;
  echo 'ciphertextReceivedBase64: ' . $ciphertextReceivedBase64 . PHP_EOL;
  $decryptedtext = rsaDecryptionOaepSha256(loadRsaPrivateKeyPem(), base64Decoding($ciphertextReceivedBase64));
  echo 'decryptedtext: ' . $decryptedtext . PHP_EOL;

?>

但是,当我尝试运行此 PHP 代码时,我收到以下输出,让我卡住了:

.:/opt/alt/php70/usr/share/pear:../inc/phpseclib
RSA 2048 encryption OAEP SHA-256 string
plaintext: The quick brown fox jumps over the lazy dog

* * * encrypt the plaintext with the RSA public key * * *
<br />
<b>Fatal error</b>:  Uncaught Error: Class name must be a valid object or a string in /home/.../inc/phpseclib/Math/BigInteger.php:182
Stack trace:
#0 /home/.../inc/phpseclib/Crypt/Common/AsymmetricKey.php(143): phpseclib3\Math\BigInteger-&gt;__construct(0)
#1 /home/.../inc/phpseclib/Crypt/Common/AsymmetricKey.php(162): phpseclib3\Crypt\Common\AsymmetricKey::initialize_static_variables()
#2 /home/.../inc/phpseclib/Crypt/PublicKeyLoader.php(45): phpseclib3\Crypt\Common\AsymmetricKey::load('\r\n-----BEGIN PU...', false)
#3 /home/.../main/phpseclibtest.php(19): phpseclib3\Crypt\PublicKeyLoader::load('\r\n-----BEGIN PU...')
#4 /home/.../main/phpseclibtest.php(94): rsaEncryptionOaepSha256('\r\n-----BEGIN PU...', 'The quick brown...')
#5 main
  thrown in <b>/home/.../inc/phpseclib/Math/BigInteger.php</b> on line <b>182</b><br />

如果有帮助,请注意测试脚本位于单独的目录中,如下所示:

inc
-> phpseclib (the PHPSecLib library with all subdirectories)
main
-> phpseclibtest.php (my test script)

PHP 版本是 7.0.33,如果这有什么不同的话。

我真的很想弄清楚如何让 PHPSecLib 工作。如果有人可以帮助我弄清楚发生了什么,那就太棒了。

【问题讨论】:

【参考方案1】:

您正在尝试使用 phpseclib v2 的说明安装 phpseclib v3。有两种选择:

选项 1:将 PHPSecLib V3 与 Composer 一起使用

此选项需要在服务器上进行 SSH 访问。

要安装 phpseclib v3,您需要 Composer。安装完成后,您可以执行 composer initcomposer require phpseclib/phpseclib:~3.0

通过这样做,您可以替换它:

  ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL);
  header("Content-Type: text/plain");
  $sIncludePath = get_include_path() . PATH_SEPARATOR . '../inc/phpseclib';
  echo $sIncludePath."\n";
  set_include_path($sIncludePath);

  include('Crypt/Common/AsymmetricKey.php');
  include('Math/BigInteger.php');
  include('Crypt/EC.php');
  include('Crypt/PublicKeyLoader.php');
  include('Crypt/RSA.php');

有了这个:

require __DIR__ . '/vendor/autoload.php'; 

一旦你这样做了,phpseclib v3 应该可以顺利运行。您遇到的问题是由于 phpseclib v3 正在尝试自动加载引擎,它无法做到这一点,因为没有自动加载器。

请注意,使用生成的代码后,不需要 SSH。要让 PHPSecLib v3 为没有 SSH 的人工作,您可以做的是在本地执行 composer init 然后 composer require phpseclib/phpseclib:3.0 然后获取您的供应商目录以及您的 composer.json 和 composer.lock 文件并将其放入任何你想要的项目。 IE。最终用户不会运行作曲家 - 您将运行作曲家。您将下载依赖项,而他们只会使用您下载的依赖项!

选项 2:手动使用 PHPSecLib2

此选项不需要 SSH。 PHPSecLib2 的功能比 PHPSecLib3 少,但它仍然得到积极维护。 (甚至 PHPSecLib1 也会定期更新。)

PHPSecLib2 没有 PublicKeyLoader 类,因此您可以使用 RSA 类,如下所示:

<?php

  ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL);
  header("Content-Type: text/plain");
  $sIncludePath = get_include_path() . PATH_SEPARATOR . '../s/phpseclib';
  echo $sIncludePath."\n";
  set_include_path($sIncludePath);

  include('Math/BigInteger.php');
  include('Crypt/RSA.php');
  include('Crypt/Hash.php');
  include('Crypt/Random.php');

  use phpseclib\Crypt\RSA;
  use phpseclib\Crypt\Hash;
  use phpseclib\Crypt\Random;

  function rsaEncryptionOaepSha256 ($publicKey, $plaintext) 
    $rsa = new RSA;
    $rsa->loadKey($publicKey);
    $rsa->setHash('sha256');
    $rsa->setMGFHash('sha256');
    return $rsa->encrypt($plaintext);
  

  function rsaDecryptionOaepSha256 ($privateKey, $ciphertext) 
    $rsa = new RSA;
    $rsa->loadKey($privateKey);
    $rsa->setHash('sha256');
    $rsa->setMGFHash('sha256');
    return $rsa->decrypt($ciphertext);
  
  
  function loadRsaPrivateKeyPem() 
    // this is a sample key - don't worry !
    return '
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDwSZYlRn86zPi9
e1RTZL7QzgE/36zjbeCMyOhf6o/WIKeVxFwVbG2FAY3YJZIxnBH+9j1XS6f+ewjG
FlJY4f2IrOpS1kPiO3fmOo5N4nc8JKvjwmKtUM0t63uFFPfs69+7mKJ4w3tk2mSN
4gb8J9P9BCXtH6Q78SdOYvdCMspA1X8eERsdLb/jjHs8+gepKqQ6+XwZbSq0vf2B
MtaAB7zTX/Dk+ZxDfwIobShPaB0mYmojE2YAQeRq1gYdwwO1dEGk6E5J2toWPpKY
/IcSYsGKyFqrsmbw0880r1BwRDer4RFrkzp4zvY+kX3eDanlyMqDLPN+ghXT1lv8
snZpbaBDAgMBAAECggEBAIVxmHzjBc11/73bPB2EGaSEg5UhdzZm0wncmZCLB453
XBqEjk8nhDsVfdzIIMSEVEowHijYz1c4pMq9osXR26eHwCp47AI73H5zjowadPVl
uEAot/xgn1IdMN/boURmSj44qiI/DcwYrTdOi2qGA+jD4PwrUl4nsxiJRZ/x7PjL
hMzRbvDxQ4/Q4ThYXwoEGiIBBK/iB3Z5eR7lFa8E5yAaxM2QP9PENBr/OqkGXLWV
qA/YTxs3gAvkUjMhlScOi7PMwRX9HsrAeLKbLuC1KJv1p2THUtZbOHqrAF/uwHaj
ygUblFaa/BTckTN7PKSVIhp7OihbD04bSRrh+nOilcECgYEA/8atV5DmNxFrxF1P
ODDjdJPNb9pzNrDF03TiFBZWS4Q+2JazyLGjZzhg5Vv9RJ7VcIjPAbMy2Cy5BUff
EFE+8ryKVWfdpPxpPYOwHCJSw4Bqqdj0Pmp/xw928ebrnUoCzdkUqYYpRWx0T7YV
RoA9RiBfQiVHhuJBSDPYJPoP34kCgYEA8H9wLE5L8raUn4NYYRuUVMa+1k4Q1N3X
Bixm5cccc/Ja4LVvrnWqmFOmfFgpVd8BcTGaPSsqfA4j/oEQp7tmjZqggVFqiM2m
J2YEv18cY/5kiDUVYR7VWSkpqVOkgiX3lK3UkIngnVMGGFnoIBlfBFF9uo02rZpC
5o5zebaDImsCgYAE9d5wv0+nq7/STBj4NwKCRUeLrsnjOqRriG3GA/TifAsX+jw8
XS2VF+PRLuqHhSkQiKazGr2Wsa9Y6d7qmxjEbmGkbGJBC+AioEYvFX9TaU8oQhvi
hgA6ZRNid58EKuZJBbe/3ek4/nR3A0oAVwZZMNGIH972P7cSZmb/uJXMOQKBgQCs
FaQAL+4sN/TUxrkAkylqF+QJmEZ26l2nrzHZjMWROYNJcsn8/XkaEhD4vGSnazCu
/B0vU6nMppmezF9Mhc112YSrw8QFK5GOc3NGNBoueqMYy1MG8Xcbm1aSMKVv8xba
rh+BZQbxy6x61CpCfaT9hAoA6HaNdeoU6y05lBz1DQKBgAbYiIk56QZHeoZKiZxy
4eicQS0sVKKRb24ZUd+04cNSTfeIuuXZrYJ48Jbr0fzjIM3EfHvLgh9rAZ+aHe/L
84Ig17KiExe+qyYHjut/SC0wODDtzM/jtrpqyYa5JoEpPIaUSgPuTH/WhO3cDsx6
3PIW4/CddNs8mCSBOqTnoaxh
-----END PRIVATE KEY-----
';
  

  function loadRsaPublicKeyPem() 
    // this is a sample key - don't worry !
    return '
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8EmWJUZ/Osz4vXtUU2S+
0M4BP9+s423gjMjoX+qP1iCnlcRcFWxthQGN2CWSMZwR/vY9V0un/nsIxhZSWOH9
iKzqUtZD4jt35jqOTeJ3PCSr48JirVDNLet7hRT37Ovfu5iieMN7ZNpkjeIG/CfT
/QQl7R+kO/EnTmL3QjLKQNV/HhEbHS2/44x7PPoHqSqkOvl8GW0qtL39gTLWgAe8
01/w5PmcQ38CKG0oT2gdJmJqIxNmAEHkatYGHcMDtXRBpOhOSdraFj6SmPyHEmLB
ishaq7Jm8NPPNK9QcEQ3q+ERa5M6eM72PpF93g2p5cjKgyzzfoIV09Zb/LJ2aW2g
QwIDAQAB
-----END PUBLIC KEY-----
';
  

  function base64Encoding ($input) 
    return base64_encode($input);
  
  function base64Decoding ($input) 
    return base64_decode($input);
  

  echo 'RSA 2048 encryption OAEP SHA-256 string' . PHP_EOL;
  $sDataToEncrypt = "The quick brown fox jumps over the lazy dog";
  echo 'plaintext: ' . $sDataToEncrypt . PHP_EOL;

  // encryption
  echo PHP_EOL . '* * * encrypt the plaintext with the RSA public key * * *' .PHP_EOL;
  $ciphertextBase64 = base64Encoding(rsaEncryptionOaepSha256(loadRsaPublicKeyPem(), $sDataToEncrypt));
  echo 'ciphertextBase64: ' . $ciphertextBase64 . PHP_EOL;

  // transport the encrypted data to recipient

  // receiving the encrypted data, decryption
  echo PHP_EOL . '* * * decrypt the ciphertext with the RSA private key * * *' .PHP_EOL;
  $ciphertextReceivedBase64 = $ciphertextBase64;
  echo 'ciphertextReceivedBase64: ' . $ciphertextReceivedBase64 . PHP_EOL;
  $decryptedtext = rsaDecryptionOaepSha256(loadRsaPrivateKeyPem(), base64Decoding($ciphertextReceivedBase64));
  echo 'decryptedtext: ' . $decryptedtext . PHP_EOL;

?>

要手动降级到 PHPSecLib2 并让上述代码正常工作,您需要将 phpseclib 目录替换为位于此 GitHub 上的文件:https://github.com/phpseclib/phpseclib/tree/2.0

【讨论】:

@azoundria - 在 composer.json 中列举了一些依赖项,但之后会自动加载内容。 biginteger 引擎是自动加载的,对于公钥,插件都是自动加载的,并且很多 ASN.1 映射都是自动加载的。大约有 100 个 ASN.1 地图。手动包含这些而不是使用自动加载器将是大量的工作。现在,您可以在没有 composer 的情况下进行自动加载,但您仍然需要管理依赖项。 phpseclib v2 没有任何其他依赖项,因此您只需要一个自动加载器 @azoundria - 对于 v2,您可以在不使用所有 Composer 的情况下使用 Composer 的自动加载器:phpseclib.sourceforge.net/2.0.html 就此而言,用通用 PSR-4 自动加载器替换 Composer 的自动加载器可能就足够了。但是 v2 的自动加载也不像 v3 那样繁重 @azoundria - “但是,v2 是否意味着它的特性或功能比 v3 少得多,并且可能无法继续维护(例如新发现的安全漏洞)?” v1 已经 15 岁了,并且仍在更新。根据 github,它在 5 天前进行了更新。我认为您不必担心很快就会放弃 v2。至于更少的功能......是的v2确实有更少的功能。 v2 仅支持 RSA 而 v3 支持椭圆曲线和 DSA 等 至于让 v3 为没有 SSH 的人工作....这是有可能的!你可以做的是在本地做composer init 然后composer require phpseclib/phpseclib:3.0 然后把你的vendor 目录和你的composer.jsoncomposer.lock 文件放到你想要的任何项目中。 IE。最终用户不会运行 composer - you 将运行 composer。 将下载依赖项,而他们只会使用您下载的依赖项! @azoundria - pastebin.com/9arwu3TJ 应该可以解决问题!为简洁起见,我在特定于 phpseclib 的代码之后没有包含任何内容。

以上是关于“类名必须是有效的对象或字符串”在没有 Composer 的情况下安装 PHPSecLib的主要内容,如果未能解决你的问题,请参考以下文章

如何修复 laravel 5.2 zizaco 委托:迁移类名验证?

markdown Serviços - InjeçãodeDependência(DI)+ como usarumeserviçoemum compo

json 此片段用于以下知识库文章 - https://kb.wpbeaverbuilder.com/article/220-installl-beaver-builder-via-compos

WslRegisterDistribution failed with error: 0x8007019e The Windows Subsystem for Linux optional compo

组件没有在 $emit 上刷新范围

没有 Composer 的 Paypal 核心 SDK