You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

220 lines
5.0 KiB

<?php
class Crypt
{
// 配置
public $config;
// 错误信息
public $err_msg = '';
/**
* 构造函数
*/
public function __construct(array $config)
{
$this->config = $config;
}
/**
* 数据校验
* @param array $data 待校验数据
* @return bool
*/
private function checkData(array $data)
{
// 非空校验
if( count($data) == 0 )
{
$this->err_msg = '待签名数据为空';
return false;
}
// 一维数组校验
if( count($data) != count($data, 1) )
{
$this->err_msg = '待签名数据不能是多维数组';
return false;
}
return true;
}
/**
* 生成签名
* @param array $data 待签名数据
* @return bool|string
*/
public function makeSign(array $data)
{
// 数据校验
$check_data = $this->checkData($data);
if($check_data === false)
{
return false;
}
// 升序排列
ksort($data);
// 转字符串
$pre_sign_str = http_build_query($data);
// echo "[pre_sign_str(jiao yi message)]: {$pre_sign_str}";
// die();
// 读取私钥
$private_key = file_get_contents($this->config['private_key']);
$private_key = openssl_pkey_get_private($private_key);
// 私钥签名
$res = openssl_sign($pre_sign_str, $sign, $private_key);
if($res === false)
{
$this->err_msg = openssl_error_string();
return false;
}
// 签名转Base64
$sign = base64_encode($sign);
return $sign;
}
/**
* 校验签名
* @param array $data 待校验数据
* @param string $sign 签名
* @return bool
*/
public function checkSign(array $data, string $sign)
{
// 数据校验
$check_data = $this->checkData($data);
if($check_data === false)
{
return false;
}
// 签名转二进制
$sign = base64_decode($sign);
// 升序排列
ksort($data);
// 转字符串
$pre_sign_str = http_build_query($data);
$pre_sign_str = urldecode($pre_sign_str);
// echo "[pre sign str]: {$pre_sign_str}";
// die();
// 读取公钥
$public_key = file_get_contents($this->config['public_key']);
$public_key = openssl_pkey_get_public($public_key);
// 公钥验签
$res = openssl_verify($pre_sign_str, $sign, $public_key);
if($res === false)
{
$this->err_msg = openssl_error_string();
return false;
}
return $res;
}
/**
* 加密交易报文
* @param array $data 待签名数据
* @return bool|string
*/
public function encryptTradeData(array $data)
{
// 数据校验
$check_data = $this->checkData($data);
if($check_data === false)
{
return false;
}
// 读取公钥
$public_key = file_get_contents($this->config['public_key']);
$public_key = openssl_pkey_get_public($public_key);
// 公钥长度(bit)
$public_key_info = openssl_pkey_get_details($public_key);
$public_key_bit = $public_key_info['bits'];
// 数据长度(数据长度=密钥字节数-11,11为OPENSSL_PKCS1_PADDING的填充长度)
$data_length = $public_key_bit / 8 - 11;
// 待加密数据转json
$pre_encrypt_data = json_encode($data, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
// 按密钥长度拆分数据
$pre_encrypt_data_arr = str_split($pre_encrypt_data, $data_length);
// 分段公钥加密
$crypted_data = '';
foreach($pre_encrypt_data_arr as $key=>$val)
{
$res = openssl_public_encrypt($val, $crypted_data_tmp, $public_key, OPENSSL_PKCS1_PADDING);
if($res === false)
{
$this->err_msg = openssl_error_string();
return false;
}
$crypted_data .= $crypted_data_tmp;
}
// 加密结果转Base64
$crypted_data = base64_encode($crypted_data);
return $crypted_data;
}
/**
* 解密交易报文
* @param string $data 加密的交易报文
* @return bool|array
*/
public function decryptTradeData($data)
{
// 加密数据转二进制
$pre_decrypt_data = base64_decode($data);
// 读取私钥
$private_key = file_get_contents($this->config['private_key']);
$private_key = openssl_pkey_get_private($private_key);
// 私钥长度(bit)
$private_key_info = openssl_pkey_get_details($private_key);
$private_key_bit = $private_key_info['bits'];
// 数据长度(数据长度=密钥字节数,解密时无需考虑OPENSSL_PKCS1_PADDING的填充占位)
$data_length = $private_key_bit / 8;
// 按密钥长度拆分数据
$pre_decrypt_data_arr = str_split($pre_decrypt_data, $data_length);
// 分段私钥解密
$decrypted_data = '';
foreach($pre_decrypt_data_arr as $key=>$val)
{
$res = openssl_private_decrypt($val, $decrypted_data_tmp, $private_key, OPENSSL_PKCS1_PADDING);
if($res === false)
{
$this->err_msg = openssl_error_string();
return false;
}
$decrypted_data .= $decrypted_data_tmp;
}
// 解密结果编码转换(JAVA处理后的中文一般为GBK编码)
// echo "\r\n";
// var_dump($decrypted_data);
$charset = mb_detect_encoding($decrypted_data); // 这个东西有点问题 解析出来是false 先不用了
// echo "\r\n";
// var_dump($charset);
// echo "\r\n";
$decrypted_data = mb_convert_encoding($decrypted_data, 'UTF-8', 'GBK');
// echo "\r\n";
// var_dump($decrypted_data);
return $decrypted_data;
}
}
?>