PHP實現RSA2加密

因爲做支付寶APP支付需要把訂單信息結合支付密鑰進行加密,所以需要一個完成加密的接口。

整體代碼下面會有,不過在代碼之前有幾個需要注意的點。

首先,php擴展openssl需要打開,這個可以phpinfo查看是否開啓。

Linux寶塔是上安裝的php是默認開啓的

接着,在php.ini文件中搜索extension,找到extension = openssl去掉前面的冒號

在phpstudy中是extension = openssl.dll

這裏有一點,好多博文都沒有提到,所以我踩過這個坑。(就是密鑰和公鑰的格式問題)

 private static $PRIVATE_KEY = <<<EOD
-----BEGIN RSA PRIVATE KEY-----
這裏是密鑰內容
-----END RSA PRIVATE KEY-----
EOD;
   
   private static $PUBLIC_KEY  = <<<EOD
-----BEGIN PUBLIC KEY-----
這裏是公鑰內容
-----END PUBLIC KEY-----
EOD;

如果想把代碼放到.pem文件中,也用這種格式,之後使用file_get_contents()函數獲取到即可

還有一點需要注意,PHP傳參會自動轉義,如果是把加密功能寫成一個接口,那麼需要加密的數據就會以參數的形式傳進來,就需要解決PHP轉義這個問題。

假設 $data是傳來的參數

$str = htmlspecialchars_decode($data);

這個函數,可以把參數進行反轉義,變回最初的樣子。

下面是一個可以單獨執行的php代碼,可以直接測試加密和驗證

<?php

class Rsa2
{
    private static $PRIVATE_KEY = <<<EOD
-----BEGIN RSA PRIVATE KEY-----
////////
-----END RSA PRIVATE KEY-----
EOD;
   
   private static $PUBLIC_KEY  = <<<EOD
-----BEGIN PUBLIC KEY-----
\\\\\\\\
-----END PUBLIC KEY-----
EOD;

    /**
     * 獲取私鑰
     * @return bool|resource
     */
    private static function getPrivateKey()
    {
        $privKey = self::$PRIVATE_KEY;
        return openssl_pkey_get_private($privKey);
    }

    /**
     * 獲取公鑰
     * @return bool|resource
     */
    private static function getPublicKey()
    {
        $publicKey = self::$PUBLIC_KEY;
        return openssl_pkey_get_public($publicKey);
    }

    /**
     * 創建簽名
     * @param string $data 數據
     * @return null|string
     */
    public function createSign($data = '')
    {
        if (!is_string($data)) {
            return null;
        }
        return openssl_sign(
                    $data,
                    $sign,
                    self::getPrivateKey(),
                    OPENSSL_ALGO_SHA256
                  ) ? urlencode(base64_encode($sign)) : null;
    }

    /**
     * 驗證簽名
     * @param string $data 數據
     * @param string $sign 簽名
     * @return bool
     */
    public function verifySign($data = '', $sign = '')
    {
        if (!is_string($sign) || !is_string($sign)) {
            return false;
        }
        return (bool)openssl_verify(
                      $data,
                      base64_decode($sign),
                      self::getPublicKey(),
                      OPENSSL_ALGO_SHA256
                    );
    }
}


$rsa2 = new Rsa2();
$content = 'app_id=2019121069836088&biz_content={"timeout_express":"30m","product_code":"QUICK_MSECURITY_PAY","total_amount":"0.01","subject":"1","body":"我是測試數據","out_trade_no":"12345678"}&charset=utf-8&method=alipay.trade.app.pay&sign_type=RSA2&timestamp=2020-01-04 16:55:53&version=1.0'; //待簽名字符串

$strSign = $rsa2->createSign($content);      //生成簽名

echo "原文 --> $content\n";
echo "簽名後 --> $strSign\n";

$is_ok = $rsa2->verifySign($content, $strSign); //驗證簽名0 

echo "驗證簽名 --> $is_ok\n";

加密之後驗證加密是否正確,就調用驗證的方法,驗證方法的參數1爲原字符串,參數2爲加密後的字符串,結果放回1爲驗證成功。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章