前情提要
考虑到大家对支付的加密解密的问题,所以紧跟上一期写出了这篇实战。
配置类
<?php
class Config
{
/**
* 创建密钥的配置
* @var array
*/
public static $config = [
"digest_alg" => "sha512", // 文摘
"private_key_bits" => 4096, // 私钥位 字节数
"private_key_type" => OPENSSL_KEYTYPE_RSA, // 加密密钥类型
"config" => "/etc/ssl/openssl.cnf"
];
public static $privateKeypass = 123456; // 加密密钥
public static $pfxpath = 'test_cer.pfx'; // 证书
public static $cerpath = 'test_cer.cer'; // 证书
public static $pripem = "private_test.pem"; // 私钥
public static $pubpem = "public_test.pem"; // 公钥
}
自动加载类
<?php
spl_autoload_extensions(".php");
$path = __DIR__;
set_include_path($path);
spl_autoload_register();
生成公钥密钥
<?php
class KeyGenerator
{
// 新的私钥
protected $res;
// 密钥key
private $privateKey;
// 公钥key
private $publicKey;
// 配置
public $generatorConfig;
/**
* 初始化时 生成一个新的私钥
* @throws Exception
*/
public function __construct()
{
$this->generatorConfig = Config::$config;
$this->res = openssl_pkey_new($this->generatorConfig);
if (empty($this->res)) {
throw new Exception('生成密钥失败');
}
}
/**
* 生成密钥
* @throws Exception
*/
protected function generatePrivateKey()
{
openssl_pkey_export($this->res,$this->privateKey , null, $this
->generatorConfig);
if (empty($this->privateKey)) {
throw new Exception('生成私钥失败');
}
}
/**
* @throws Exception
*/
protected function generatePublicKey()
{
$resKey = openssl_pkey_get_details($this->res);
if (empty($resKey['key'])) {
throw new Exception('生成公钥失败');
}
$this->publicKey = $resKey['key'];
}
/**
* 生成公钥与密钥文件
* @throws Exception
*/
public function generate()
{
$this->generatePublicKey();
$this->generatePrivateKey();
file_put_contents(__DIR__."/public_test.pem", $this->publicKey);
file_put_contents(__DIR__."/private_test.pem", $this->privateKey);
openssl_free_key($this->res);
}
}
生成证书
<?php
class Certificate
{
private $expireDays = 365;
protected $dn = array(
"countryName" => "ZG", //所在国家
"stateOrProvinceName" => "Guangdong", //所在省份
"localityName" => "Guangzhou", //所在城市
"organizationName" => "The Brain Room Limited", //注册人姓名
"organizationalUnitName" => "PHP Documentation Team", //组织名称
"commonName" => "Wez Furlong", //公共名称
"emailAddress" => "123456@qq.com" //邮箱
);
/**
* @param string $privateKey
*/
public function generate()
{
$privateKey = file_get_contents(__DIR__.'/'.Config::$pripem);
$csr = openssl_csr_new($this->dn, $privateKey, Config::$config);
$sscert = openssl_csr_sign($csr, null, $privateKey, $this->expireDays, Config::$config);
openssl_x509_export($sscert, $csrkey);
openssl_pkcs12_export($sscert, $prikey, $privateKey, Config::$privateKeypass);
$cerpath = __DIR__.'/'.Config::$cerpath;
$pfxpath = __DIR__.'/'.Config::$pfxpath;
file_put_contents($cerpath,$csrkey);
file_put_contents($pfxpath, $prikey);
}
}
加签验签
<?php
class Sign
{
/**
* 私钥加秘
* @return string
* @throws Exception
*/
public function encrypted()
{
$pfxPath = __DIR__.'/'.Config::$pfxpath;
if (! file_exists($pfxPath)) {
throw new Exception('文件不存在');
}
$privKey = file_get_contents($pfxPath);
$data = 'php是世界上最好的语言';
openssl_pkcs12_read($privKey, $certs, Config::$privateKeypass);
$privKeyId = $certs['pkey'];
openssl_sign($data, $sign, $privKeyId, OPENSSL_ALGO_SHA1);
return base64_encode($sign);
}
/**
* 公钥解密
* @param string $sign
* @throws Exception
*/
public function decrypted(string $sign)
{
$data = 'php是世界上最好的语言';
$unsign = base64_decode($sign);
// $pfxPath = __DIR__.'/'.Config::$pfxpath;
// if (! file_exists($pfxPath)) {
// throw new Exception('文件不存在');
// }
// $privkey = file_get_contents($pfxPath);
// openssl_pkcs12_read($privkey,$certs, Config::$privateKeypass);
// $publickId = $certs['cert'];
// $flag = (bool)openssl_verify($text, $sign, $pubKeyId);
$cerPath = __DIR__.'/'.Config::$cerpath;
$publicKey = file_get_contents($cerPath);
if (! file_exists($cerPath)) {
throw new Exception('不存在');
}
$pubKeyId = openssl_get_publickey($publicKey);
$flag = (bool)openssl_verify($data, $unsign, $pubKeyId,OPENSSL_ALGO_SHA1);
echo $flag ? '证书验证成功'.PHP_EOL : '证书验证失败'.PHP_EOL;
}
}
测试类
<?php
require __DIR__.'/autoload.php';
try {
if (! isset($argv[1])) {
// 使用默认的证书做验证
$sign = new Sign();
$signMsg = $sign->encrypted();
$sign->decrypted($signMsg);
exit;
}
if (! in_array($argv[1], ['key', 'cer', 'sign'])) {
throw new Exception('参数错误');
}
switch ($argv[1]) {
case 'key':
$generator = new KeyGenerator(); // 生成密钥
$generator->generate();
echo '生成密钥成功'.PHP_EOL;
break;
case 'cer':
$cer = new Certificate(); // 生成证书
$cer->generate();
echo '生成证书成功'.PHP_EOL;
break;
default:
$sign = new Sign();
$signMsg = $sign->encrypted(); // 验证
$sign->decrypted($signMsg);
break;
}
} catch (Throwable $e) {
var_dump($e);
}
github仓库地址
仓库地址:https://github.com/feng8605765/openssl-rsa-sign