ここ 2 日間私を悩ませていた PHP RSA 署名検証問題がついに解決しました。これまで RSA とはあまり接点がなかったのと、公式の PHP SDK がまだ参照できないため、少し回り道をしてみました。あなたと共有するためにここに書きました。
Alipay は関連する SDK を正式に提供していませんが、これは実際には非常に重要です。不慣れなため、問題が発生したときに、PHP が RSA 署名をサポートしていないのではないかと考えてしまいます。前に進むモチベーションがなくなってしまいます。実際、率直に言って、MD5 署名と RSA 署名の違いは署名方法だけです。その他はすべて同じです。ここでは主に署名と署名検証に RSA を使用する方法について説明します。
まず以下のものを準備する必要があります:
署名検証メソッド openssl_verify は、php の openssl 拡張機能にカプセル化されています。
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 には必要ありません。
Alipay 公開キー:
マニュアルに従って、サインプラットフォームで入手してください。
直接コピーすると文字列が得られるので、次のように変換する必要があります。
1) スペースを改行に変換します
2) コメントを追加します
たとえば、コピーした公開キーは次のとおりです: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRBMjkaBznjXk06ddsL751KyYt
ztPFg0D3tu7jLqCacgqL+lbshIaItDGEXAMZmKa3DV6Wxy+l48YMo0RyS+dWze4M
UmuxHU/v6tiT0ZTXJN3EWrjCtCyyttdv/ROB3CkheXnTKB76reTkQqg57OWW+m9j
TCoccYMDXEIWYTs3CwIDAQAB、変換後:
-----公開鍵の開始-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRBMjkaBznjXk06ddsL751KyYt
ztPFg0D3tu7jLqCacgqL+lbshIaItDGEXAMZmKa3DV6Wxy+l48YMo0RyS+dWze4M
UmuxHU/v6tiT0ZTXJN3EWrjCtCyyttdv/ROB3CkheXnTKB76reTkQqg57OWW+m9j
TCoccYMDXEIWYTs3CwIDAQAB
-----エンドパブリックキー-----
公開キーをファイルに保存します。
この 2048 ビットの公開キーは 1 行ではなく 9 行または 10 行である必要があることに注意してください。そうしないと、PHP の openssl_pkey_get_public を読み取ることができず、-----BEGIN PUBLIC KEY--- がない場合、pub_key_id の結果は false になります。 - - と -----END PUBLIC KEY----- は自分で追加し、最終的に rsa_public_key.pem ファイルに保存できます。
さて、すべてが揃ったので、最初に署名関数を見てみましょう:
コードをコピー
1
2 /**
3 * 署名文字列
4 * @param $prestr 署名が必要な文字列
5 * 署名結果を返す
6*/
7 関数 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
2 /**
3 * 署名を確認します
4 * @param $prestr 署名が必要な文字列
5 * @param $sign 署名結果
6 * 署名結果を返す
7*/
8 関数 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 true を返します;
18 }その他{
19 return false;
20 }
21 }
22 ?>
コードをコピー
注:
1.$prestrの内容はMD5と同じです(マニュアル参照)
2.$sign は、Alipay インターフェースによって返される Sign パラメーターのbase64_decode によってデコードされたバイナリです
3. 署名検証に Alipay 公開キーを使用する
4. この関数は、署名検証が成功したかどうかを直接示すブール値を返します
Alipay が公式に提供する PHP 版 SDK デモは MD5 暗号化方式のみを処理しますが、Android および iOS 端末が Alipay 暗号化方式を要求する場合、現時点ではサーバー側 PHP は RSA 暗号化アルゴリズムのみを使用できます。署名を検証する必要があるため、デモにいくつかの変更を加えます。
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 行目
関数 getSignVeryfy($para_temp, $sign) {
が
に変更されました
関数 getSignVeryfy($para_temp, $sign, $sign_type) {
getSignVeryfy 関数 127 行目
switch (strtoupper(trim($this->alipay_config['sign_type']))) {
ケース「MD5」:
$isSgin = md5Verify($prestr, $sign, $this->alipay_config['key']);
休憩;
デフォルト:
$isSgin = false;
}
が
に変更されました
switch (strtoupper(trim($sign_type))) {
ケース「MD5」:
$isSgin = md5Verify($prestr, $sign, $this->alipay_config['key']);
休憩;
ケース「RSA」:
$isSgin = rsaVerify($prestr, $sign);
休憩
デフォルト:
$isSgin = false;
}
2. 新しいalipay_rsa.function.phpファイルを作成します
コードをコピー
1
2 /* *
3 * RSA
4 * 詳細: RSA 暗号化
5 * バージョン: 3.3
6 * 日付: 2014-02-20
7 * 説明:
8 * 以下のコードは、マーチャントのテストを容易にするために提供されるサンプル コードにすぎません。マーチャントは、自分の Web サイトのニーズに応じて、このコードを作成できます。このコードを使用する必要はありません。
9 * このコードは、Alipay インターフェースの学習と研究のみを目的としており、参考としてのみ提供されています。
10 */
11 /**
12 * 署名文字列
13 * @param $prestr 署名が必要な文字列
14 * 署名結果を返す
15*/
16 関数 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 * 署名結果を返す
29*/
30 関数 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 true を返します;
40}その他{
41 return false;
42 }
43 }
44 ?>
コードをコピー
最後に言いたいのは、公式マニュアルは基本的に正しいですが、あまり詳しくない箇所もありますので、開発の際にはもっと参考にしてください。
http://www.bkjia.com/PHPjc/735876.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/735876.html技術記事ここ 2 日間私を悩ませていた PHP RSA 署名検証問題がついに解決しました。これまで RSA とはあまり接点がなかったのと、公式の PHP SDK がまだ参照できないため、少し回り道をしてみました。書きました...