PHP 实现RSA方式签名认证

RSA签名规则实现:

基本请求规则

  • client商户发起请求时, 需要对请求参数生成签名。
  • service商户接收异步通知时,需要验证参数中的签名。
  • RSA方式签名 --> 商户需要创建一对RSA秘钥,将公钥传给平台(service),私钥自行留存用于生成签名。 同时平台也会提供一个公钥给商户,用于验证签名。

 

签名算法

  • Setp.1 确定待签名参数

在请求参数列表中,除去sign参数外,其他需要使用到的参数皆是要签名的参数。

在通知返回参数列表中,除去sign参数外,凡是通知返回回来的参数皆是要签名的参数。

  • Setp.2 对参数进行排序

对于待签名的所有参数,需要根据参数名首字符字典顺序(ascii值大小)排序,若遇到相同首字符,则判断第二个字符,以此类推。

  • Setp.3 生成待签名字符串

将排序后的待签名参数以“&“符号拼接, 形如:“参数名1=参数值1&参数名2=参数值2&….&参数名N=参数值N”。

  • Setp.4 生成签名/验证签名

生成签名:把待签名字符串与商户的私钥一同放入RSA的签名函数中进行签名运算,从而得到签名结果字符串(sign值)。

验证签名:把待签名字符串、平台提供的公钥、通知返回参数中的参数sign值三者一同放入RSA的签名函数中进行签名运算,来判断签名是否验证通过。

  • Setp.5 生成签名php用例
$pubKey = '-----BEGIN PUBLIC KEY-----
XXXXXXXXXXXXXXXXQEBAQUAA4GNADCBiQKBgQCD9glEeniobNraIF3MsFPQQ4h0
4Yu7e4g60MjTcJzgj1Dgfbap0a4r/Fg9b6ltsUhuJFkCsWoMinNzQ+9iSlb7nHo9
yRYNKBUaFocaj/pAjPCUmRzo5ieszhjSInR8/aMNqNIy7KLlkiogh1Bc6/m5S6IA
aXbUyiIooas3XXXXXXXXXXX
-----END PUBLIC KEY-----';

$priKey ='-----BEGIN RSA PRIVATE KEY-----
XXXXXXXXXXXXXXXXXXXXXXXbNraIF3MsFPQQ4h04Yu7e4g60MjTcJzgj1Dgfbap
0a4r/Fg9b6ltsUhuJFkCsWoMinNzQ+9iSlb7nHo9yRYNKBUaFocaj/pAjPCUmRzo
5ieszhjSInR8/aMNqNIy7KLlkiogh1Bc6/m5S6IAaXbUyiIooas367NwCQIDAQAB
AoGAVtkKaGMiHdbmgkBi+1/hCWQo3qPCTvWSRwM56M5osPIhjF2wZjt1ocVGXcir
fWH8BWEuo7MX1IEaUnYXilzauXPQHkH6cfMjF3uTLq+RAWWPyevTduqOm7jHM08l
XzfH74q2qtMCMtWQcElhHPlfRFySgDmX9g4V6OLXxH3Dx8ECQQCywdfXb38tg0Il
9b6rkP92G7rXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXVytigEJZOYpZ9W
K0wzQgC9AkEAvPuYzwIZwcBKDBd1eALghN1B6ZKdIQ+vCMpezMormuOcR9Ls+JtR
RapOxsmqWUc5jJOkeTYY0kLgFntj44H/PQJALaEvkI2kgCCmTPxK3I6ZtzNi6nvL
kkmIPry9iKCIFqL/2u/QR/TiYC4RG6PtMBzkC8EVu+E/qNJ2Ns+8lsT9XQJAUmnW
BdCAswHMSOGiFKgMiWSD7fxGEbjpOAgot14jDfTcnmXZecEh/CN9Hyuq4iwxaKCq
RUHWKTuIxcUhloGGcQJAZ9DzAb/N2wAVATm8fX5e3gps3w+31mOVoemtBJA86QVe
gd+5SE3mDQP9DPOp0WaXXXXXXayK/elsg2/zl9JeOoQ==
-----END RSA PRIVATE KEY-----';


$params = [
    "merchant_id"=>"1",
    "uid"=>"2122334455",
    "out_trade_id"=>"13423423423",
    "amount"=>"88",
    "subject"=>"活动红包"
];

//获取预处理字符串
$signString = getSignString($params);

//预处理字符串为
//amount=88&merchant_id=1&out_trade_id=13423423423&subject=活动红包&uid=2122334455

//获取签名
$sign = getSign($signString,$priKey);

//生成的签名为
//Najkbz6vZx1+HTpsmyeeawAUCbfpY2o2k/TAuhnZncf1KJ+DjfHK8q3+3Bo2pYYush98lsxLJ4Mv+C5qOZEYzdNbC/EIxfuR/Gx46Nrh8KK999NmSOpT0qaBfsVE7VIEPHQLFwieI7SWU/sOeBiEubXCyZUffSxKJLLnp1mKq9k=


//验证签名
$res = checkSign($pubKey,$sign,$signString);
var_dump($res);

//结果为 true


/**
 * 生成签名
 * @param    string     $signString 待签名字符串
 * @param    [type]     $priKey     私钥
 * @return   string     base64结果值
 */
function getSign($signString,$priKey){
    $privKeyId = openssl_pkey_get_private($priKey);
    $signature = '';
    openssl_sign($signString, $signature, $privKeyId);
    openssl_free_key($privKeyId);
    return base64_encode($signature);
}

/**
 * 校验签名
 * @param    string     $pubKey 公钥
 * @param    string     $sign   签名
 * @param    string     $toSign 待签名字符串
 * @return   bool
 */
function checkSign($pubKey,$sign,$toSign){
    $publicKeyId = openssl_pkey_get_public($pubKey);
    $result = openssl_verify($toSign, base64_decode($sign), $publicKeyId);
    openssl_free_key($publicKeyId);
    return $result === 1 ? true : false;
}

/**
 * 获取待签名字符串
 * @param    array     $params 参数数组
 * @return   string
 */
function getSignString($params){
    unset($params['sign']);
    ksort($params);
    reset($params);

    $pairs = array();
    foreach ($params as $k => $v) {
        if(!empty($v)){
            $pairs[] = "$k=$v";
        }
    }

    return implode('&', $pairs);
}

注意

1.生成PKCS1的秘钥对 私钥和公钥
2.将PKCS1的秘钥转换成PKCS8的秘钥
3.PKCS8的秘钥供java使用
4.PKCS1的公钥供php使用

秘钥对生成方式

  • 生成私钥:openssl genrsa -out rsa_private_key.pem 1024
  • 生成公钥: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

 

PHP校验秘钥格式:

公钥校验:openssl_pkey_get_public()

私钥校验:openssl_pkey_get_private()     ----非法返回false

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值