php - 无法使用 phpseclib 类

标签 php encryption phpseclib

我已经从 github 安装了 phpseclib 库,我正在尝试使用 PHP 加密密码(用于 Steam 社区)。我可以通过使用 Steam 在他们网站上的 javascript 代码来使用 Javascript 来做到这一点,但我无法使用纯 PHP 加密密码。

Javascript 加密代码:

var RSAPublicKey = function($modulus_hex, $encryptionExponent_hex) {
    this.modulus = new BigInteger( $modulus_hex, 16);
    this.encryptionExponent = new BigInteger( $encryptionExponent_hex, 16);
};

var Base64 = {
    base64: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
    encode: function($input) {
        if (!$input) {
            return false;
        }
        var $output = "";
        var $chr1, $chr2, $chr3;
        var $enc1, $enc2, $enc3, $enc4;
        var $i = 0;
        do {
            $chr1 = $input.charCodeAt($i++);
            $chr2 = $input.charCodeAt($i++);
            $chr3 = $input.charCodeAt($i++);
            $enc1 = $chr1 >> 2;
            $enc2 = (($chr1 & 3) << 4) | ($chr2 >> 4);
            $enc3 = (($chr2 & 15) << 2) | ($chr3 >> 6);
            $enc4 = $chr3 & 63;
            if (isNaN($chr2)) $enc3 = $enc4 = 64;
            else if (isNaN($chr3)) $enc4 = 64;
            $output += this.base64.charAt($enc1) + this.base64.charAt($enc2) + this.base64.charAt($enc3) + this.base64.charAt($enc4);
        } while ($i < $input.length);
        return $output;
    },
    decode: function($input) {
        if(!$input) return false;
        $input = $input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
        var $output = "";
        var $enc1, $enc2, $enc3, $enc4;
        var $i = 0;
        do {
            $enc1 = this.base64.indexOf($input.charAt($i++));
            $enc2 = this.base64.indexOf($input.charAt($i++));
            $enc3 = this.base64.indexOf($input.charAt($i++));
            $enc4 = this.base64.indexOf($input.charAt($i++));
            $output += String.fromCharCode(($enc1 << 2) | ($enc2 >> 4));
            if ($enc3 != 64) $output += String.fromCharCode((($enc2 & 15) << 4) | ($enc3 >> 2));
            if ($enc4 != 64) $output += String.fromCharCode((($enc3 & 3) << 6) | $enc4);
        } while ($i < $input.length);
        return $output;
    }
};

var Hex = {
    hex: "0123456789abcdef",
    encode: function($input) {
        if(!$input) return false;
        var $output = "";
        var $k;
        var $i = 0;
        do {
            $k = $input.charCodeAt($i++);
            $output += this.hex.charAt(($k >> 4) &0xf) + this.hex.charAt($k & 0xf);
        } while ($i < $input.length);
        return $output;
    },
    decode: function($input) {
        if(!$input) return false;
        $input = $input.replace(/[^0-9abcdef]/g, "");
        var $output = "";
        var $i = 0;
        do {
            $output += String.fromCharCode(((this.hex.indexOf($input.charAt($i++)) << 4) & 0xf0) | (this.hex.indexOf($input.charAt($i++)) & 0xf));
        } while ($i < $input.length);
        return $output;
    }
};

var RSA = {

    getPublicKey: function( $modulus_hex, $exponent_hex ) {
        return new RSAPublicKey( $modulus_hex, $exponent_hex );
    },

    encrypt: function($data, $pubkey) {
        if (!$pubkey) return false;
        $data = this.pkcs1pad2($data,($pubkey.modulus.bitLength()+7)>>3);
        if(!$data) return false;
        $data = $data.modPowInt($pubkey.encryptionExponent, $pubkey.modulus);
        if(!$data) return false;
        $data = $data.toString(16);
        if(($data.length & 1) == 1)
            $data = "0" + $data;
        return Base64.encode(Hex.decode($data));
    },

    pkcs1pad2: function($data, $keysize) {
        if($keysize < $data.length + 11)
            return null;
        var $buffer = [];
        var $i = $data.length - 1;
        while($i >= 0 && $keysize > 0)
            $buffer[--$keysize] = $data.charCodeAt($i--);
        $buffer[--$keysize] = 0;
        while($keysize > 2)
            $buffer[--$keysize] = Math.floor(Math.random()*254) + 1;
        $buffer[--$keysize] = 2;
        $buffer[--$keysize] = 0;
        return new BigInteger($buffer);
    }
};

为了加密它,我只需调用以下代码:
var pubKey = RSA.getPublicKey('<?php echo $curl->response->publickey_mod; ?>', '<?php echo $curl->response->publickey_exp; ?>');
var encrypted_password = RSA.encrypt('<?php echo $inviter['password']; ?>', pubKey);

当我尝试从 phpseclib 包含一个文件并使用该类时,该文件包含成功,但该类显示一个错误,指出它不是一个有效的类。

我的PHP代码:
<?php
// publickey_mod = C2242A41A84E56D9CD7952CCB985343A6DCE26AF7CA31036415B7B9DA190DF68BBEC93ED6A9AAE5CA9D6EB1A65244E0013DB38C9462076F8165EDB2A1ECB383A75FB0C71388AFD2C2DC15F9088BA252B4ED2F2C304F545C3704B6B7F5CEE01AF7DD0DC9038CBFBDE7B99689006C5272EBCEC221DB3D9CEB8514E246A571E49709AD94442A8611BE131E6F3FFA40AD632BBD6C5B5F85F7A5C87310E17632145A57BDF17A4F7305E959B4A6126AA8C64C794975F17051E6EAF5462F1189AAD0E7B5F2F254AEEB030D8ED8BAD0F8BD753482E652FFB2405D8947994E143032D5511AF63977A51C9013B5516FA51C5AC50E56588C09C761A473E8D18566B1D435687

// publickey_exp = 010001

require_once 'phpseclib/Crypt/RSA.php';
require_once 'phpseclib/Crypt/RSA/PKCS1.php';

$pkcs = new \phpseclib\Crypt\RSA\PKCS1();

$key = $pkcs->savePublicKey(new \phpseclib\Math\BigInteger(C2242A41A84E56D9CD7952CCB985343A6DCE26AF7CA31036415B7B9DA190DF68BBEC93ED6A9AAE5CA9D6EB1A65244E0013DB38C9462076F8165EDB2A1ECB383A75FB0C71388AFD2C2DC15F9088BA252B4ED2F2C304F545C3704B6B7F5CEE01AF7DD0DC9038CBFBDE7B99689006C5272EBCEC221DB3D9CEB8514E246A571E49709AD94442A8611BE131E6F3FFA40AD632BBD6C5B5F85F7A5C87310E17632145A57BDF17A4F7305E959B4A6126AA8C64C794975F17051E6EAF5462F1189AAD0E7B5F2F254AEEB030D8ED8BAD0F8BD753482E652FFB2405D8947994E143032D5511AF63977A51C9013B5516FA51C5AC50E56588C09C761A473E8D18566B1D435687, 16), new \phpseclib\Math\BigInteger(010001, 16));

$rsa = new phpseclib\Crypt\RSA();

$rsa->setPrivateKeyFormat(CRYPT_RSA_PRIVATE_FORMAT_PKCS1);
$rsa->setPublicKeyFormat(CRYPT_RSA_PUBLIC_FORMAT_PKCS1);

$rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
define('CRYPT_RSA_PKCS15_COMPAT', true);
$rsa->loadKey($key);

$password = $rsa->encrypt("mySteamPassword");    // encrypting password

var_dump($password);

?>

以及此代码显示的错误消息:
Fatal error: Class 'phpseclib\Crypt\RSA\PKCS' not found in C:\xampp\htdocs\RSA-Encryption\phpseclib\Crypt\RSA\PKCS1.php on line 40

最佳答案

看到这部分了吗?

require_once 'phpseclib/Crypt/RSA.php';
require_once 'phpseclib/Crypt/RSA/PKCS1.php';


您明确包含依赖于其他类的特定类,但不直接包含它们。正确的解决方案是,而不是输入 require_once直接声明,使用自动加载器。

如果你使用 composer 加载这个库, 这很简单。
  • 运行 composer require phpseclib/phpseclib
  • 添加 require_once 'vendor/autoload.php';到您的 PHP 脚本。

  • 否则,您需要使用 spl_autoload_register()反而:
    /**
     * Register a PSR autoloader for a given namespace and directory
     * 
     * @param string $namespace
     * @param string $dir
     * @param string $type ('psr0' or 'psr4')
     * @return boolean
     * @throws Exception
     * @ref http://stackoverflow.com/a/35015933/2224584
     */
    function generic_autoload($namespace, $dir, $type = 'psr4')
    {
        switch ($type) {
            case 'psr0':
                $spl = '_';
                break;
            case 'psr4':
                $spl = '\\';
                break;
            default:
                throw new Exception('Invalid type; expected "psr0" or "psr4"');
        }
        $ns = trim($namespace, DIRECTORY_SEPARATOR.$spl);
    
        return spl_autoload_register(
            function($class) use ($ns, $dir, $spl)
            {
                // project-specific namespace prefix
                $prefix = $ns.$spl;
    
                // base directory for the namespace prefix
                $base_dir =  $dir . DIRECTORY_SEPARATOR;
    
                // does the class use the namespace prefix?
                $len = strlen($prefix);
                if (strncmp($prefix, $class, $len) !== 0) {
                    // no, move to the next registered autoloader
                    return;
                }
    
                // get the relative class name
                $relative_class = substr($class, $len);
    
                // replace the namespace prefix with the base directory, replace
                // namespace separators with directory separators in the relative 
                // class name, append with .php
                $file = $base_dir .
                    str_replace($spl, DIRECTORY_SEPARATOR, $relative_class) .
                    '.php';
    
                // if the file exists, require it
                if (file_exists($file)) {
                    require $file;
                }
            }
        );
    }
    

    用法:
    generic_autoload('phpseclib', '/path/to/phpseclib', 'psr4');
    

    注意事项: Make sure you aren't using PKCS1v1.5 padding for RSA encryption .如果你打算使用 RSA,你应该使用 RSAES-OAEP with MGF1+SHA256 and e = 65537 .我知道 phpseclib 支持这个;如果 Steam 社区不这样做,那就大惊小怪,直到他们这样做为止。

    关于php - 无法使用 phpseclib 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34972748/

    相关文章:

    php - 如何在 .htaccess 中创建别名以更改本地 URL

    php - 如何将以逗号分隔的数据添加到数据库

    java - 为什么这个 AES 实现会解包并再次包装 key ?

    ios - 解密保存在钥匙串(keychain)中的字符串

    java - php中的RSA加密到JAva中的RSA解密

    PHPSECLIB读取目录的总大小?

    php - php 版本的切换在 mac 上不起作用

    php - 迭代列

    iOS - 使用 TLS-PSK 连接到套接字

    file-upload - PHP 中的 ftp 上传是如何工作的?