PHP支付寶介面RSA驗證

來源:互聯網
上載者:User
這兩天一直困擾的PHP RSA簽名驗證問題終於解決了,由於之前RSA接觸的不多,再加上官方至今還未有PHP的SDK可供參考,因此走了一些彎路,寫在這裡和大家分享。    雖然支付寶官方還未提供相關SDK,PHP確實可以實現RSA方式的簽名,這點其實很重要,由於不熟悉,在遇到困難的時候,經常會不由自主地想到是否PHP不支援RSA簽名,乾脆用MD5得了,這樣就沒有了前進的動力。其實說穿了MD5和RSA簽名,不同的只是簽名方式的區別,其他的都一樣,因此我這裡主要說一下如何用RSA進行簽名和驗簽。     首先你需要準備下面的東西:    php的openssl擴充裡已經封裝好了驗簽的方法openssl_verify。    如果在Windows下的php.ini需要開啟Openssl模組: extension=php_openssl.dll     商戶私密金鑰:    即RSA私密金鑰,按照手冊,按以下方式產生:     openssl genrsa -out rsa_private_key.pem 1024      商戶公開金鑰:    即RSA私密金鑰,按照手冊,按以下方式產生:    openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem     產生之後,按照手冊的說明,需要在簽約平台上傳公開金鑰,需要注意的是,上傳的時候需要把所有的注釋和換行都去掉。      另外手冊中還有如下命令:    openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt     該命令將RSA私密金鑰轉換成PKCS8格式,對於PHP來說,不需要。      支付寶公開金鑰:    根據手冊,在簽約平台獲得。    如果你直接複製下來的話,會得到一個字串,需要進行下面的轉換;    1)把空格變成換行    2)添加註釋    比如你複製下來的公開金鑰是:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRBMjkaBznjXk06ddsL751KyYt ztPFg0D3tu7jLqCacgqL+lbshIaItDGEXAMZmKa3DV6Wxy+l48YMo0RyS+dWze4MUmuxHU/v6tiT0ZTXJN3EwrjCtCyyttdv/ROB3CkheXnTKB76reTkQqg57OWW+m9jTCoccYMDXEIWYTs3CwIDAQAB,那轉換之後為:    -----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRBMjkaBznjXk06ddsL751KyYtztPFg0D3tu7jLqCacgqL+lbshIaItDGEXAMZmKa3DV6Wxy+l48YMo0RyS+dWze4MUmuxHU/v6tiT0ZTXJN3EwrjCtCyyttdv/ROB3CkheXnTKB76reTkQqg57OWW+m9jTCoccYMDXEIWYTs3CwIDAQAB-----END PUBLIC KEY-----    把公開金鑰儲存在檔案裡。  注意這個是2048位的公開金鑰應該是9行或者10行,不能為1行,不然PHP的openssl_pkey_get_public無法讀取,pub_key_id的結果為false,如果沒有-----BEGIN PUBLIC KEY----- 和 -----END PUBLIC KEY----- 可以自己加上,最後儲存到一個rsa_public_key.pem檔案中。 好了,現在已經有了所有的東西,先看簽名函數:  複製代碼 1 <?php 2 /** 3  * 簽名字串 4  * @param $prestr 需要簽名的字串 5  * return 簽名結果 6  */ 7 function rsaSign($prestr) { 8     $public_key= file_get_contents('rsa_private_key.pem'); 9     $pkeyid = openssl_get_privatekey($public_key);10     openssl_sign($prestr, $sign, $pkeyid);11     openssl_free_key($pkeyid);12     $sign = base64_encode($sign);13     return $sign;14 }15 ?>複製代碼注意點:1.$prestr的內容和MD5一樣(參見手冊,但不包含最後的MD5密碼)2.簽名用商戶私密金鑰3.最後的簽名,需要用base64編碼4.這個函數返回的值,就是這次請求的RSA簽名。 驗簽函數: 複製代碼 1 <?php 2 /** 3  * 驗證簽名 4  * @param $prestr 需要簽名的字串 5  * @param $sign 簽名結果 6  * return 簽名結果 7  */ 8 function rsaVerify($prestr, $sign) { 9     $sign = base64_decode($sign);10     $public_key= file_get_contents('rsa_public_key.pem');11     $pkeyid = openssl_get_publickey($public_key);12     if ($pkeyid) {13         $verify = openssl_verify($prestr, $sign, $pkeyid);14         openssl_free_key($pkeyid);15     }16     if($verify == 1){17         return true;18     }else{19         return false;20     }21 }22 ?>複製代碼注意點:1.$prestr的內容和MD5一樣(參見手冊)2.$sign是支付寶介面返回的sign參數用base64_decode解碼之後的二進位3.驗簽用支付寶公開金鑰4.這個函數返回一個布爾值,直接告訴你,驗簽是否通過   支付寶官方提供的PHP版SDK demo中只對MD5加密方式進行了處理,但android 端和ios端 請求支付寶加密方式只能用RSA密碼編譯演算法,這時服務端PHP就無法驗證簽名了,所以需要對demo進行一些修改。 1、修改alipay_notify.class.php檔案 verifyNotify 函數第46行 $isSign = $this->getSignVeryfy($_POST, $_POST["sign"]); 改成$isSign = $this->getSignVeryfy($_POST, $_POST["sign"], $_POST["sign_type"]);  verifyReturn 函數第83行$isSign = $this->getSignVeryfy($_GET, $_GET["sign"]); 改成 $isSign = $this->getSignVeryfy($_GET, $_GET["sign"], $_GET["sign_type"]);   getSignVeryfy 函數 116行function getSignVeryfy($para_temp, $sign) {改成function getSignVeryfy($para_temp, $sign, $sign_type) {  getSignVeryfy 函數 127行switch (strtoupper(trim($this->alipay_config['sign_type']))) {    case "MD5" :        $isSgin = md5Verify($prestr, $sign, $this->alipay_config['key']);break;    default :        $isSgin = false;} 改成switch (strtoupper(trim($sign_type))) {    case "MD5" :        $isSgin = md5Verify($prestr, $sign, $this->alipay_config['key']);break;    case "RSA" :        $isSgin = rsaVerify($prestr, $sign);        break;     default :        $isSgin = false;}  2、建立一個alipay_rsa.function.php檔案複製代碼 1 <?php 2 /* * 3  * RSA 4  * 詳細:RSA加密 5  * 版本:3.3 6  * 日期:2014-02-20 7  * 說明: 8  * 以下代碼只是為了方便商戶測試而提供的範例代碼,商戶可以根據自己網站的需要,按照技術文檔編寫,並非一定要使用該代碼。 9  * 該代碼僅供學習和研究支付寶介面使用,只是提供一個參考。10  */11 /**12  * 簽名字串13  * @param $prestr 需要簽名的字串14  * return 簽名結果15  */16 function rsaSign($prestr) {17     $public_key= file_get_contents('rsa_private_key.pem');18     $pkeyid = openssl_get_privatekey($public_key);19     openssl_sign($prestr, $sign, $pkeyid);20     openssl_free_key($pkeyid);21     $sign = base64_encode($sign);22     return $sign;23 }24 /**25  * 驗證簽名26  * @param $prestr 需要簽名的字串27  * @param $sign 簽名結果28  * return 簽名結果29  */30 function rsaVerify($prestr, $sign) {31     $sign = base64_decode($sign);32     $public_key= file_get_contents('rsa_public_key.pem');33     $pkeyid = openssl_get_publickey($public_key);34     if ($pkeyid) {35         $verify = openssl_verify($prestr, $sign, $pkeyid);36         openssl_free_key($pkeyid);37     }38     if($verify == 1){39         return true;40     }else{41         return false;42     }43 }44 ?>複製代碼最後要說的是官方提供的手冊上說的基本上都是正確的,只是有些地方沒有說的很詳細,開發的時候一定要多參考,大致就是這樣,祝大家好運。

相關文章

Beyond APAC's No.1 Cloud

19.6% IaaS Market Share in Asia Pacific - Gartner IT Service report, 2018

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。