RSA非对称密钥接口开发文档

1、RSA加签:

1.1、规则:XML报文head的各个域(sign除外)与报文data各个域均看作String类型,按Key值字典序排序后得到待加签的内容,用自己商户的私钥对待加签的内 容进行MD5withRSA签名,再做Base64编码后作为sign值
例如待签名的值为:“1LTTV027430187654321测试商户pay00011.0”(amount的值+ appId的值+ mchntCd的值+ mchntNm的值+ msgId的值+ reqNo 的值+ version的值)
$header = [];
$postData = [];
$all = array_merge($header, $postData);
ksort($all);
$str = '';
foreach ($all as $key => $value) {
$str .= $value;
}
xyz = $this->userSign($str);

假如签名后为xyz

1.2、然后:将签名的结果放到<sign></sign>标签中得到 <sign>xyz</sign>

2、RSA报体加密

2.1、规则:用平台公钥对待加密报文体 使用RSA算法 进行分段加密(原始加签前的字符串转换成字节,再将字节按照117个字符加密一次,然后把所有的密文拼接成一个密文,将加密结果转换成base64的格式)。

//请求体数据加密
$postData = [];
ksort($postData);
$xml = "";
foreach ($postData as $key => $val) {
$xml .= "<" . $key . ">" . $val . "</" . $key . ">";
}
sec123 = $this->userEncryption($platform_id,$xml);


2.2、比如加密后得到结果为 sec123
将加密后的内容放到<data></data>标签中<data>sec123</data>

3、组合成发送报文

经过上面两步加密后,最终得到的发送报文为:
<xml>
    <head>
        <appId>LTTV</appId>
        <version>1.0</version>
        <msgId>pay</msgId>
        <reqNo>0001</ reqNo>
        <sign>xyz</sign>
    </head>
    <data>sec123</data>
</xml>

4、RSA报体验签


4.1、规则:响应报文转成数组互获取加密报文体,对报文体解密,解密后的报文体与报文头组装成非加密报文,按加签规则得到验签字符串
$result = $model->xmlToArray($res); //响应报文由xml字符串转出数组
$data = $result['data'];
$result['data'] = $model->userDecrypt($data); //对报文体加密数据进行解密操作
$data = '<xml>'.$result['data'].'</xml>'; //解密后的xml字符串需要添加根元素
$data = $model->xmlToArray($data); //报文体数据进行验签操作
$result['data'] = $data;
$signresult = $model->userVerify($result); //用户用平台公钥验签

5、RSA报体解密


5.1、规则:解密的时候需要讲密文解码,再128个字符解密一下,然后拼接成数据
$data = sec123
$result['data'] = $model->userDecrypt($data); //对报文体加密数据进行解密操作
$data = '<xml>'.$result['data'].'</xml>'; //解密后的xml字符串需要添加根元素
$data = $model->xmlToArray($data); //报文体数据进行验签操作

5.2、$result['data']为解密结果

备注:

/**
* 用户解密数据
* @param $data
* @return string
*/
public function userDecrypt($data){

    $result = '';
    $data = str_split(base64_decode($data), 128);
    $pem = getCoKey('co_private'); //用户私钥解密
    $key = openssl_pkey_get_private($pem);
    foreach($data as $chunk)
    {

        openssl_private_decrypt($chunk,$decrypted,$key,OPENSSL_PKCS1_PADDING);
        $result .= $decrypted;

    }
    return $result;

}

/**
* 用户私钥加签
* @param $data
* @param int $signMethod
* @return bool|string
*/
public function userSign($data,$signMethod=OPENSSL_ALGO_MD5){

    $pem = getCoKey('co_private'); //用户私钥加签
    $res = openssl_pkey_get_private($pem);
    if (openssl_sign($data, $out, $res, $signMethod)) {

        openssl_free_key($res); //释放资源
        return (base64_encode($out));

    }
    return false;

}

/**
* 用户验签函数
* @param $res
* @return bool|int
*/
public function userVerify($res){

    try {

        //验签数据准备 降维 排序 拼接 验签
        $tmp = array();
        foreach($res as $ke => $val){

            if(!empty($val)||$val == 0){

                foreach($val as $k=>$v){

                    if(!empty($v||$v == 0)){

                        $tmp[$k]=$v;

                    }

                }

            }

        }
        unset($tmp['sign']);
        ksort($tmp);
        $str = '';
        foreach ($tmp as $key => $value){
        $str .= $value;
        }
        $platform_id = getPlatformId($res['head']['mchid']);
        $result = $this->userVerifySign($platform_id,$res['head']['sign'],$str,OPENSSL_ALGO_MD5);
        trace($result,'验签结果');
        return $result;

    } catch (Exception $e) {

        trace($e->getMessage());
        return false;

    }

}

/**
* 用户验签
* @param $co_platform_id
* @param $sign
* @param $data
* @param int $signMethod
* @return int
*/
public function userVerifySign($co_platform_id,$sign, $data,$signMethod = OPENSSL_ALGO_SHA1)
{

    $pem = getPlatformPublicKey($co_platform_id); //用户用平台公钥验签
    trace($pem,'平台公钥');
    $verifyKey = openssl_pkey_get_public($pem);
    $sign = base64_decode($sign);
    $r = openssl_verify($data, $sign, $verifyKey, $signMethod);
    openssl_free_key($verifyKey);
    return $r;

}

/**
* 平台公钥加密
* @param $co_platform_id
* @param $data
* @return string
*/
public function userEncryption($co_platform_id,$data){

    $inputs = str_split($data,117);
    $result = '';
    $pem = getPlatformPublicKey($co_platform_id); //平台公钥加密
    foreach ($inputs as $input){

        openssl_public_encrypt($input,$output,$pem,OPENSSL_PKCS1_PADDING);
        $result .= $output;

    }
    return base64_encode($result);

}

相关文档

评论0条