私钥公钥获取方式如下:
①. 访问在线生成非对称加密公钥私钥对: http://web.chacuo.net/netrsakeypair
点击生成密钥对,删除RSA生成格式-> BEGIN RSA PRIVATE KEY 和 END PUBLIC KEY ,即第一行和最后一行。
②. 访问在线字符串文本压缩工具,删除文本中的所有新行、制表键、空格、回车、换行 字符: http://www.ab173.com/other/compress.php
将生成的公钥和私钥复制到压缩文本框中去除换行和空格
③. 把公钥上传至商户后台,平台会使用该公钥进行解密并且验签。
④. 私钥自己隐秘保存(加密用)。
<?php
/**
* Description: 平台公钥解密获取数据(验签)
* Date: 2022/7/1
* @param $data
*/
public function decrypt($data)
{
ksort($data);
$toSign = '';
foreach ($data as $key => $value) {
if (strcmp($key, 'sign') != 0 && $value != '') {
$toSign .= $key . '=' . $value . '&';
}
}
$str = rtrim($toSign, '&');
$encrypted = '';
// 公钥
$pem = chunk_split($this->platform_public_key, 64, "\n");
$pem = "-----BEGIN PUBLIC KEY-----\n" . $pem . "-----END PUBLIC KEY-----\n";
$publickey = openssl_pkey_get_public($pem);
$base64 = str_replace(array('-', '_'), array('+', '/'), $data['sign']);
$crypto = '';
foreach (str_split(base64_decode($base64), 128) as $chunk) {
openssl_public_decrypt($chunk, $decrypted, $publickey);
$crypto .= $decrypted;
}
if ($str != $crypto) {
// 验签失败
exit('Signature verification failed');
}
}
/**
* Description: 私钥加密生成签名
* Date: 2022/7/1
* @param $data
* @return mixed
*/
public function encrypt($data)
{
ksort($data);
$str = '';
foreach ($data as $k => $v) {
if (!empty($v)) {
$str .= (string)$k . '=' . $v . '&';
}
}
$str = rtrim($str, '&');
$encrypted = '';
// 私钥
$pem = chunk_split($this->mch_private_key, 64, "\n");
$pem = "-----BEGIN PRIVATE KEY-----\n" . $pem . "-----END PRIVATE KEY-----\n";
$private_key = openssl_pkey_get_private($pem);
$crypto = '';
foreach (str_split($str, 117) as $chunk) {
openssl_private_encrypt($chunk, $encryptData, $private_key);
$crypto .= $encryptData;
}
$encrypted = base64_encode($crypto);
$encrypted = str_replace(array('+', '/', '='), array('-', '_', ''), $encrypted);
$data['sign'] = $encrypted;
return $data;
}