wechatpay-guzzle-middleware icon indicating copy to clipboard operation
wechatpay-guzzle-middleware copied to clipboard

SensitiveInfoCrypto 这个类过度设计了,看起来简单,其实并不简单

Open ifreesec opened this issue 3 years ago • 7 comments

ifreesec avatar Jul 15 '20 03:07 ifreesec

另外传进去的证书也不一定要是 resource 啊,放缓存里也是可以的吧

ifreesec avatar Jul 15 '20 03:07 ifreesec

@TheNorthMemory

@ifreesec 有什么建议吗,另外也欢迎PR。

xy-peng avatar Jul 15 '20 03:07 xy-peng

传入的$publicCert参数类型为resource其实本意是指使用PemUtil::loadCertificate或者openssl_x509_read返回的EVP_PKEY resource,而不是要从文件读取的resource。 如果证书放缓存里,可以借助PemUtil::loadCertificateFromString实现,这样使用 $encryptor = new SensitiveInfoCrypto(PemUtil::loadCertificateFromString('缓存的证书'));

tpirc3 avatar Jul 15 '20 07:07 tpirc3

传入的$publicCert参数类型为resource其实本意是指使用PemUtil::loadCertificate或者openssl_x509_read返回的EVP_PKEY resource,而不是要从文件读取的resource。 如果证书放缓存里,可以借助PemUtil::loadCertificateFromString实现,这样使用 $encryptor = new SensitiveInfoCrypto(PemUtil::loadCertificateFromString('缓存的证书'));

这个理解了,感谢

ifreesec avatar Jul 15 '20 07:07 ifreesec

@TheNorthMemory

@ifreesec 有什么建议吗,另外也欢迎PR。

我的想法很简单,就是按正常的方法去使用加密和解密,正常的拆分成两个类

//加密
class SensitiveInfoEncrypt
{
    /**
     * string 的话可以 PemUtil::loadCertificateFromString 处理下在传入
     *
     * @var resource|null $publicCert The public certificate
     */
    private $publicCert;

    /**
     * SensitiveInfoEncrypt constructor.
     * @param null $publicCert 微信支付平台证书
     */
    public function __construct($publicCert)
    {
        $this->publicCert = $publicCert;
    }

    /**
     * @param $str
     * @return string
     */
    public function encrypt($str)
    {
        if (!is_resource($this->publicCert)) {
            throw new \InvalidArgumentException('The publicCert must be resource.');
        }
        openssl_public_encrypt($str, $encrypted,
            $this->publicCert, \OPENSSL_PKCS1_OAEP_PADDING);

        return \base64_encode($encrypted);
    }
}

//解密
class SensitiveInfoDecrypt
{
    /**
     * @var resource|null $privateKey The private key
     */
    private $privateKey;

    /**
     * SensitiveInfoDecrypt constructor.
     * @param null $privateKey 微信商户私钥
     */
    public function __construct($privateKey = null)
    {
        $this->privateKey = $privateKey;
    }

    /**
     * 解密
     * @param $str
     * @return string
     */
    public function decrypt($str)
    {
        if (!is_resource($this->privateKey)) {
            throw new \InvalidArgumentException('The privateKey must be resource.');
        }
        openssl_private_decrypt(\base64_decode($str), $decrypted,
            $this->privateKey, \OPENSSL_PKCS1_OAEP_PADDING);

        return $decrypted;
    }
}

@xy-peng

ifreesec avatar Jul 15 '20 08:07 ifreesec

刚看到提醒,抱歉。 楼主批评得对,这用法上基本都是单一场景,要么加密,要么解密,俩揉在一起是有点过度设计了,而且容易造成干扰。。。

TheNorthMemory avatar Jul 15 '20 11:07 TheNorthMemory

新包设计上,加/解密用法是:

  • WeChatPay\Crypto\Rsa::encrypt(string $plaintext, $publicKey)
  • WeChatPay\Crypto\Rsa::decrypt(string $ciphertext, $privateKey)

环境要求 ^PHP7.2.5 || ^8.0 -> https://github.com/wechatpay-apiv3/wechatpay-php

TheNorthMemory avatar Jun 18 '21 05:06 TheNorthMemory