前言
在对接各种支付的过程中,md5签名方式比较常见。而采用rsa签名的比较少。rsa的性能开销相对于md5大一些。
- 安全性高
- 完整性验证
- 身份认证
- 应用广泛
rsa签名方法
rsa签名的方法生成一个类,方便调用。
<?php
class RsaUtils{
/**
* 签名算法,SHA256WithRSA
*/
private const SIGNATURE_ALGORITHM = OPENSSL_ALGO_SHA256;
/**
* RSA最大加密明文大小
*/
private const MAX_ENCRYPT_BLOCK = 117;
/**
* RSA最大解密密文大小
*/
private const MAX_DECRYPT_BLOCK = 128;
private $publicKey; // 私有化公钥内容,不要头尾和换行符,只要内容
private $privateKey; // 私有化私钥内容,不要头尾和换行符,只要内容
public function __construct($publicKey, $privateKey) {
$this->publicKey = $publicKey;
$this->privateKey = $privateKey;
}
/**
* 获取完整的私钥
* @return bool|resource
*/
private function _getPrivateKey()
{
$privateKey = "-----BEGIN RSA PRIVATE KEY-----" . PHP_EOL;
$privateKey .= wordwrap($this->privateKey, 64, "\n", true);
$privateKey .= "\n-----END RSA PRIVATE KEY-----";
$privateKey = preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $privateKey);
//return openssl_pkey_get_private($privateKey);
return $privateKey;
}
/**
* 获取完整的公钥
* @return bool|resource
*/
private function _getPublicKey()
{
$publicKey = "-----BEGIN PUBLIC KEY-----" . PHP_EOL;
$publicKey .= wordwrap($this->publicKey, 64, "\n", true);
$publicKey .= "\n-----END PUBLIC KEY-----";
$publicKey = preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $publicKey);
//return openssl_pkey_get_public($publicKey);
return $publicKey;
}
/**
* 使用公钥将数据加密
* @param $data string 需要加密的数据
* @param $publicKey string 公钥
* @return string 返回加密串(base64编码)
*/
public function publicEncrypt($data){
$publicKey = $this->_getPublicKey();
$data = str_split($data, self::MAX_ENCRYPT_BLOCK);
$encrypted = '';
foreach($data as & $chunk){
if(!openssl_public_encrypt($chunk, $encryptData, $publicKey)){
return '';
}else{
$encrypted .= $encryptData;
}
}
return $this->_urlSafeBase64encode($encrypted);
}
/**
* 使用私钥解密
* @param $data string 需要解密的数据
* @param $privateKey string 私钥
* @return string 返回解密串
*/
public function privateDecrypt($data){
$privateKey = $this->_getPrivateKey();
$data = str_split($this->_urlSafeBase64decode($data), self::MAX_DECRYPT_BLOCK);
$decrypted = '';
foreach($data as & $chunk){
if(!openssl_private_decrypt($chunk, $decryptData, $privateKey)){
return '';
}else{
$decrypted .= $decryptData;
}
}
return $decrypted;
}
/**
* 使用私钥将数据加密
* @param $data string 需要加密的数据
* @param $privateKey string 私钥
* @return string 返回加密串(base64编码)
*/
public function privateEncrypt($data){
$privateKey = $this->_getPrivateKey();
$data = str_split($data, self::MAX_ENCRYPT_BLOCK);
//error_log(__METHOD__ . PHP_EOL .print_r($privateKey, true));
$encrypted = '';
foreach($data as & $chunk){
if(!openssl_private_encrypt($chunk, $encryptData, $privateKey)){
return '';
}else{
$encrypted .= $encryptData;
}
}
return $this->_urlSafeBase64encode($encrypted);
}
/**
* 使用公钥解密
* @param $data string 需要解密的数据
* @param $publicKey string 公钥
* @return string 返回解密串
*/
public function publicDecrypt($data){
$publicKey = $this->getPublicKey();
$data = str_split($this->urlSafeBase64decode($data), self::MAX_DECRYPT_BLOCK);
$decrypted = '';
foreach($data as & $chunk){
if(!openssl_public_decrypt($chunk, $decryptData, $publicKey)){
return '';
}else{
$decrypted .= $decryptData;
}
}
return $decrypted;
}
/**
* 私钥加签名
* @param $data 被加签数据
* @param $privateKey 私钥
* @return mixed|string
*/
public function rsaSign($data){
if(openssl_sign($data, $sign, $privateKey, self::SIGNATURE_ALGORITHM)){
return $this->_urlSafeBase64encode($sign);
}
return '';
}
/**
* 公钥验签
* @param $data 被加签数据
* @param $sign 签名
* @param $publicKey 公钥
* @return bool
*/
public function verifySign($data, $sign):bool {
$publicKey = $this->_getPublicKey();
return (1 == openssl_verify($data, $this->_urlSafeBase64decode($sign), $publicKey, self::SIGNATURE_ALGORITHM));
}
/**
* url base64编码
* @param $string
* @return mixed|string
*/
private function _urlSafeBase64encode($string){
$data = str_replace(array('+','/','='), array( '-','_',''), base64_encode($string));
return $data;
}
/**
* url base64解码
* @param $string
* @return bool|string
*/
private function _urlSafeBase64decode($string){
$data = str_replace(array('-','_'), array('+','/'), $string);
$mod4 = strlen($data) % 4;
if($mod4){
$data .= substr('====', $mod4);
}
return base64_decode($data);
}
}
调用代码
调用上面类的示例代码
//获取加密字符串
require_once('rsa.php');
$rsa = new RsaUtils($this->rsa_public_key, $this->rsa_private_key);
//字段名按照ASCII从小到大排序
ksort($Body);
$sign_str=[];
foreach($Body as $pk=>$pv){
if (empty($pv)) {
continue;
}
array_push($sign_str, "{$pk}={$pv}");
}
$unsignstr=join("&", $sign_str);
//error_log(__METHOD__ . PHP_EOL .print_r($unsignstr, true));
$checksum = $rsa->privateEncrypt($unsignstr);
$Body["sign"] = $checksum;
完整支付插件
【支付插件】woocommerce对接第三方支付smtmpay
评论 (0)