生活随笔
收集整理的這篇文章主要介紹了
PHP SHA1withRSA加密生成签名及验签
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
最近公司對(duì)接XX第三方支付平臺(tái)的代付業(yè)務(wù),由于對(duì)方公司只有JAVA的demo,所以只能根據(jù)文檔自己整合PHP的簽名加密,網(wǎng)上找過幾個(gè)方法,踩到各種各樣的坑,還好最后算是搞定了,話不多說,代碼分享出來。
?
業(yè)務(wù)要求:每個(gè)簽名組裝的內(nèi)容是按字段名的字典順序升序排序連接的
先組裝需要簽名的內(nèi)容:
?
1 /**
2 * 拼接需要簽名的內(nèi)容
3 * Author: Tao.
4 *
5 * @param array $data 需簽名的字段內(nèi)容
6 *
7 * @return string
8 */
9 public static function getSign(
$data)
10 {
11 foreach (
$data as $k =>
$v) {
12 $Parameters[
$k] =
$v;
13 }
14 //按字典序排序參數(shù)
15 ksort(
$Parameters);
16 $sign = ''
;
17 foreach (
$Parameters as $k =>
$v) {
18 $sign .=
$k . "=" .
$v . "&"
;
19 }
20 $sign = '&' .
rtrim(
$sign, '&'
);
21 return $sign;
22 }
簽名字符串如下示例:
&amount=amount 值&ccy=ccy 值 &merchantId=merchantId 值¬ifyUrl=notifyUrl 值&orderId=orderId 值 &payeeAcctNo=payeeAcctNo 值(明文)。
要注意的是,根據(jù)業(yè)務(wù)需要選擇,是否在簽名內(nèi)容前拼接 &符。
?
然后生成秘鑰簽名:
1 /**
2 * 秘鑰加密
3 * Author: Tao.
4 *
5 * @param string $data 之前生成好的需加密內(nèi)容
6 * @param $key 私鑰證書位置(.pfx文件)
7 * @param string $pwd 證書密碼
8 *
9 * @return string
10 */
11 public static function SHA1withRSA(
$data,
$key,
$pwd)
12 {
13 openssl_pkcs12_read(
file_get_contents(
$key),
$certs,
$pwd);
14 if (!
$certs)
return;
15 $signature = ''
;
16 openssl_sign(
$data,
$signature,
$certs['pkey'
]);
17 return bin2hex(
$signature);
18 }
由于第三方公司要求轉(zhuǎn)換使用16進(jìn)制,可根據(jù)需求選擇bin2hex()或base64_encode()。
這里要注意的是,根據(jù)業(yè)務(wù)需要,簽名后的內(nèi)容是否要求大小寫敏感。
簽名后的內(nèi)容應(yīng)該是小寫的,可以使用strtoupper()轉(zhuǎn)換成大寫。
以上就是給大家整理好的私鑰加密方法。
?
但此業(yè)務(wù)中另要求將銀行卡號(hào)需要進(jìn)行RSA公鑰加密
以下是獲取公鑰的方法:
此處是獲取對(duì)方平臺(tái)證書的公鑰(.cer文件)
1 /**
2 * 獲取公鑰
3 * Author: Tao.
4 *
5 * @param $path //公鑰證書位置 (.cer文件)
6 *
7 * @return mixed
8 * @throws \Exception
9 */
10 public static function loadCert(
$path)
11 {
12 $file =
file_get_contents(
$path);
13 if (!
$file) {
14 throw new \
Exception('loadx509Cert::file_get_contents ERROR'
);
15 }
16
17 $cert =
chunk_split(
base64_encode(
$file), 64, "\n"
);
18 $cert = "-----BEGIN CERTIFICATE-----\n" .
$cert . "-----END CERTIFICATE-----\n"
;
19
20 $res = openssl_pkey_get_public(
$cert);
21 $detail = openssl_pkey_get_details(
$res);
22 openssl_free_key(
$res);
23
24 if (!
$detail) {
25 throw new \
Exception('loadX509Cert::openssl_pkey_get_details ERROR'
);
26 }
27 return $detail['key'
];
28 }
29
30 /**
31 * 公鑰加密
32 * Author: Tao.
33 *
34 * @param $pubPath //公鑰證書位置 (.cer文件)
35 * @param string $bankCode //銀行卡號(hào)
36 *
37 * @return string
38 */
39 public static function rsa_encode(
$bankCode,
$pubPath)
40 {
41 $pubkey = self::loadCert(
$pubPath);
42 $encrypt_data = ''
;
43 openssl_public_encrypt(
$bankCode,
$encrypt_data,
$pubkey);
44 $encrypt_data =
base64_encode(
$encrypt_data);
45 return $encrypt_data;
46 }
你要問我為什么私鑰是bin2hex(),公鑰換了base64_encode()。我也不知道為什么,問過說是16位,但是請(qǐng)求簽名一直失敗,換了64成功了。對(duì)方說文檔太老了,忘記了。。根據(jù)需要選擇吧
?
最后回調(diào)結(jié)果驗(yàn)簽
首先先將回調(diào)數(shù)據(jù)中組裝簽名字段的內(nèi)容取出來,按上面的getSign()方法排序。
然后進(jìn)行驗(yàn)證:
1 /**
2 * 驗(yàn)證返回的簽名是否正確
3 *
4 * @param string $data 要驗(yàn)證的簽名原文
5 * @param string $signature 簽名內(nèi)容
6 *@param $pubPath 公鑰證書位置 (.cer文件)
7 *
8 * @return bool
9 */
10 public static function verifyRespondSign(
$data,
$signature,
$pubPath)
11 {
12 $keys = self::loadCert(
$pubPath);
13 $signature = hex2bin(
$signature);
14 $ok = openssl_verify(
$data,
$signature,
$keys);
15 if (
$ok == 1
) {
16 return true;
17 }
18 return false;
19 }
?
以上就是PHP SHA1withRSA加密、簽名及驗(yàn)簽的全部內(nèi)容了。
希望對(duì)各位有幫助。
有不對(duì)的地方請(qǐng)指出,及時(shí)修改,互相學(xué)習(xí)。???
轉(zhuǎn)載于:https://www.cnblogs.com/TuiHo/p/10536895.html
總結(jié)
以上是生活随笔為你收集整理的PHP SHA1withRSA加密生成签名及验签的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。