diff --git a/install.sql b/install.sql
index 4c4ab96..e0b5ea4 100644
--- a/install.sql
+++ b/install.sql
@@ -179,7 +179,11 @@ INSERT INTO `toolbox_plugin` (`id`, `title`, `alias`, `class`, `keyword`, `weigh
(92, '银行卡归属地查询', 'bankcard', 'utility\\bankcard', 'yinhangkaguishudichaxun,yhkgsdcx', 89, 1, 0, 0, 0, 3, '', '2022-10-14 16:55:08', '2022-10-21 17:35:56'),
(93, '微博图片反查', 'wbimg', 'utility\\wbimg', 'weibotupianfancha,wbtpfc', 67, 1, 0, 0, 0, 3, '', '2022-10-21 17:34:20', '2022-11-08 22:06:30'),
(94, 'QQ等级查询', 'qqlevel', 'wqq\\qqlevel', 'qqdengjichaxun,qqdjcx', 0, 0, 0, 0, 0, 5, '', '2023-04-23 18:06:05', '2023-04-23 18:06:05'),
-(95, '短视频去水印解析', 'videoparse', 'utility\\videoparse', 'duanshipinqushuiyinjiexi,dspqsyjx', 95, 1, 0, 0, 0, 3, '', '2023-09-22 23:25:17', '2023-09-28 15:29:46');
+(95, '短视频去水印解析', 'videoparse', 'utility\\videoparse', 'duanshipinqushuiyinjiexi,dspqsyjx', 95, 1, 0, 0, 0, 3, '', '2023-09-22 23:25:17', '2023-09-28 15:29:46'),
+(96, '国密SM2工具', 'guomi', 'dev\\guomi', 'guomism2,gmsm2', 0, 1, 0, 0, 19, 2, '', '2023-10-26 17:50:38', '2023-10-26 21:35:10'),
+(97, '证书信息查看', 'cert', 'dev\\cert', 'zhengshuxinxichakan,zsxxck', 0, 1, 0, 0, 18, 2, '', '2023-10-27 16:05:08', '2023-10-27 16:05:08'),
+(98, '证书格式转换', 'cert_convert', 'dev\\cert_convert', 'rsazhengshugeshizhuanhuan,rsazsgszh', 0, 1, 0, 0, 8, 2, '', '2023-10-24 21:25:15', '2023-10-27 16:03:56'),
+(99, 'CSR生成与查看', 'csr', 'dev\\csr', 'csrshengchengchakan,csrscck', 0, 1, 0, 0, 8, 2, '', '2023-11-09 20:18:19', '2023-11-10 17:14:02');
DROP TABLE IF EXISTS `toolbox_querycache`;
diff --git a/plugin/dev/cert/App.php b/plugin/dev/cert/App.php
new file mode 100644
index 0000000..8dae698
--- /dev/null
+++ b/plugin/dev/cert/App.php
@@ -0,0 +1,106 @@
+view();
+ }
+
+ public function query(){
+ if(input('post.type/d') == 2){
+ $domain = input('post.domain', null, 'trim');
+ if(!$domain) return msg('error','no domain');
+ $port = 443;
+ if(strpos($domain, ':')){
+ $a = explode(':', $domain);
+ $domain = $a[0];
+ if(is_numeric($a[1])) $port = intval($a[1]);
+ }
+ if(!checkdomain($domain)) return msg('error','域名格式不正确');
+ try{
+ $cert = $this->getSSLCertificate($domain, $port);
+ }catch(Exception $e){
+ return msg('error', $e->getMessage());
+ }
+ }else{
+ $cert = input('post.cert');
+ if(!$cert) return msg('error','no cert');
+ }
+
+ $arr = openssl_x509_parse($cert);
+ if(!$arr){
+ return msg('error', '证书文件错误');
+ }
+ $pkey_detail = openssl_pkey_get_details(openssl_pkey_get_public($cert));
+
+ $subject_info = [
+ '通用名称(CN)' => $this->format($arr['subject']['CN']),
+ '国家(C)' => $this->format($arr['subject']['C']),
+ '省份(S)' => $this->format($arr['subject']['ST']),
+ '城市(L)' => $this->format($arr['subject']['L']),
+ '组织(O)' => $this->format($arr['subject']['O']),
+ '部门(OU)' => $this->format($arr['subject']['OU']),
+ ];
+ $issuer_info = [
+ '通用名称(CN)' => $this->format($arr['issuer']['CN']),
+ '国家(C)' => $this->format($arr['issuer']['C']),
+ '组织(O)' => $this->format($arr['issuer']['O']),
+ ];
+ $cert_info = [
+ '序列号' => $arr['serialNumberHex'],
+ '签名算法' => $arr['signatureTypeSN'],
+ '密钥类型' => isset(self::$key_type[$pkey_detail['type']]) ? self::$key_type[$pkey_detail['type']] : '未知',
+ '密钥强度' => $pkey_detail['bits'],
+ '颁发时间' => date('Y-m-d H:i:s', $arr['validFrom_time_t']),
+ '过期时间' => date('Y-m-d H:i:s', $arr['validTo_time_t']),
+ '有效期' => round(($arr['validTo_time_t']-time()) / 3600 / 24).'天',
+ '备用名' => $arr['extensions']['subjectAltName'],
+ ];
+
+ return msg('ok','success',['subject_info'=>$subject_info, 'issuer_info'=>$issuer_info, 'cert_info'=>$cert_info]);
+ }
+
+ private function format($mixed){
+ if(is_array($mixed)){
+ return $mixed[array_key_first($mixed)];
+ }
+ return $mixed;
+ }
+
+ private function getSSLCertificate($domain, $port = 443) {
+ $context = stream_context_create([
+ "ssl" => [
+ "capture_peer_cert" => true,
+ ],
+ ]);
+
+ $socket = stream_socket_client('ssl://'.$domain.':'.$port, $errno, $errstr, 10, STREAM_CLIENT_CONNECT, $context);
+
+ if ($socket) {
+ $params = stream_context_get_params($socket);
+ if(!isset($params["options"]["ssl"]["peer_certificate"])){
+ throw new Exception('域名未找到SSL证书信息');
+ }
+ fclose($socket);
+ return $params["options"]["ssl"]["peer_certificate"];
+ } else {
+ $errstr = mb_convert_encoding($errstr, 'UTF-8', 'GB2312');
+ throw new Exception('域名443端口连接失败,'.$errstr);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/plugin/dev/cert/index.html b/plugin/dev/cert/index.html
new file mode 100644
index 0000000..8b2f25b
--- /dev/null
+++ b/plugin/dev/cert/index.html
@@ -0,0 +1,180 @@
+{extend name="common/plugin_layout" /}
+{block name="title"}{$plugin.title} - {:config_get('title')}{/block}
+{block name="main"}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
主题信息
+
+
+
+ | {{index}} | {{item}} |
+
+
+
+
签发者信息
+
+
+
+ | {{index}} | {{item}} |
+
+
+
+
证书信息
+
+
+
+ | {{index}} | {{item}} |
+
+
+
+
+
+
+
+{/block}
+{block name="script"}
+
+
+{/block}
\ No newline at end of file
diff --git a/plugin/dev/cert_convert/App.php b/plugin/dev/cert_convert/App.php
new file mode 100644
index 0000000..c4cf8b7
--- /dev/null
+++ b/plugin/dev/cert_convert/App.php
@@ -0,0 +1,210 @@
+view();
+ }
+
+ public function convert()
+ {
+ $from = input('post.from');
+ $to = input('post.to');
+ if(empty($from) || empty($to)) return msg('error', '必填项不能为空');
+
+ try{
+ $params = [];
+ if($from == 'PEM' && $to != 'DER' && $to != 'PKCS7'){
+ if(!isset($_FILES['private'])) return msg('error', 'PEM私钥文件不存在');
+ $private_path = $_FILES['private']['tmp_name'];
+ $this->check_cert('PEM私钥', $private_path);
+
+ if(!isset($_FILES['cert'])) return msg('error', 'PEM证书文件不存在');
+ $cert_path = $_FILES['cert']['tmp_name'];
+ $this->check_cert('PEM证书', $cert_path);
+
+ if(isset($_FILES['cacert'])){
+ $cacert_path = $_FILES['cacert']['tmp_name'];
+ $this->check_cert('PEM证书', $cacert_path);
+ file_put_contents($cert_path, PHP_EOL.file_get_contents($cacert_path), FILE_APPEND);
+ }
+
+ $params['private'] = new CURLFile($private_path);
+ $params['cert'] = new CURLFile($cert_path);
+ $params['pass'] = input('post.pass', null, 'trim');
+ $this->check_pass('证书密码', $params['pass'], true);
+ $act = $to == 'JKS' ? 'pem_to_jks' : 'pem_to_pfx';
+
+ }elseif($from == 'PEM' && $to == 'DER'){
+ if(!isset($_FILES['cert'])) return msg('error', 'PEM证书文件不存在');
+ $cert_path = $_FILES['cert']['tmp_name'];
+ $this->check_cert('PEM证书', $cert_path);
+ $params['cert'] = new CURLFile($cert_path);
+ $act = 'pem_to_der';
+
+ }elseif($from == 'DER' && $to == 'PEM'){
+ if(!isset($_FILES['cert'])) return msg('error', 'DER证书文件不存在');
+ $cert_path = $_FILES['cert']['tmp_name'];
+ $this->check_cert('DER证书', $cert_path);
+ $params['cert'] = new CURLFile($cert_path);
+ $act = 'der_to_pem';
+
+ }elseif($from == 'PKCS12'){
+ if(!isset($_FILES['cert'])) return msg('error', 'PKCS12证书文件不存在');
+ $cert_path = $_FILES['cert']['tmp_name'];
+ $this->check_cert('PKCS12证书', $cert_path);
+ $params['cert'] = new CURLFile($cert_path);
+ if($to == 'JKS'){
+ $params['srcpass'] = input('post.srcpass', null, 'trim');
+ $params['destpass'] = input('post.destpass', null, 'trim');
+ $this->check_pass('原证书密码', $params['srcpass'], true);
+ $this->check_pass('新证书密码', $params['destpass']);
+ $act = 'pfx_to_jks';
+ }elseif($to == 'PEM'){
+ $params['pass'] = input('post.pass', null, 'trim');
+ $this->check_pass('原证书密码', $params['pass'], true);
+ $act = 'pfx_to_pem';
+ }
+
+ }elseif($from == 'JKS'){
+ if(!isset($_FILES['cert'])) return msg('error', 'JKS证书文件不存在');
+ $cert_path = $_FILES['cert']['tmp_name'];
+ $this->check_cert('JKS证书', $cert_path);
+ $params['cert'] = new CURLFile($cert_path);
+ if($to == 'PKCS12'){
+ $params['srcpass'] = input('post.srcpass', null, 'trim');
+ $params['destpass'] = input('post.destpass', null, 'trim');
+ $this->check_pass('原证书密码', $params['srcpass']);
+ $this->check_pass('新证书密码', $params['destpass'], true);
+ if(empty($params['destpass'])) $params['destpass'] = $params['srcpass'];
+ $act = 'jks_to_pfx';
+ }elseif($to == 'PEM'){
+ $params['pass'] = input('post.pass', null, 'trim');
+ $this->check_pass('原证书密码', $params['pass']);
+ $act = 'jks_to_pem';
+ }
+
+ }elseif($from == 'PEM' && $to == 'PKCS7'){
+ if(!isset($_FILES['cert'])) return msg('error', 'PEM证书文件不存在');
+ $cert_path = $_FILES['cert']['tmp_name'];
+ $this->check_cert('PEM证书', $cert_path);
+
+ if(isset($_FILES['cacert'])){
+ $cacert_path = $_FILES['cacert']['tmp_name'];
+ $this->check_cert('PEM证书', $cacert_path);
+ file_put_contents($cert_path, PHP_EOL.file_get_contents($cacert_path), FILE_APPEND);
+ }
+
+ $params['cert'] = new CURLFile($cert_path);
+ $act = 'pem_to_p7b';
+
+ }elseif($from == 'PKCS7' && $to == 'PEM'){
+ if(!isset($_FILES['cert'])) return msg('error', 'PKCS7证书文件不存在');
+ $cert_path = $_FILES['cert']['tmp_name'];
+ $this->check_cert('PKCS7证书', $cert_path);
+ $params['cert'] = new CURLFile($cert_path);
+ $act = 'p7b_to_pem';
+
+ }else{
+ return msg('error', '转换类型不存在');
+ }
+
+ $response = $this->requestApi($act, $params);
+
+ $files = [];
+ if($to == 'PEM' && $from != 'DER' && $from != 'PKCS7' && substr($response, 0, 1) == '{'){
+ $arr = json_decode($response, true);
+ $files[] = ['name'=>'PEM 服务器证书', 'file'=>'cert.pem', 'data'=>base64_encode($arr['cert'])];
+ if(!empty($arr['extra_certs'])){
+ $cacert = implode(PHP_EOL, $arr['extra_certs']);
+ $files[] = ['name'=>'PEM 中间/根证书', 'file'=>'cacert.pem', 'data'=>base64_encode($cacert)];
+ }
+ $files[] = ['name'=>'PEM 私钥', 'file'=>'privatekey.pem', 'data'=>base64_encode($arr['private_key'])];
+ $files[] = ['name'=>'PEM 公钥', 'file'=>'publickey.pem', 'data'=>base64_encode($arr['public_key'])];
+ }elseif($to == 'PEM'){
+ $files[] = ['name'=>'PEM 证书文件', 'file'=>'cert.pem', 'data'=>base64_encode($response)];
+ }elseif($to == 'DER'){
+ $files[] = ['name'=>'DER 证书文件', 'file'=>'cert.der', 'data'=>base64_encode($response)];
+ }elseif($to == 'PKCS12'){
+ $files[] = ['name'=>'PKCS12 证书文件', 'file'=>'cert.pfx', 'data'=>base64_encode($response)];
+ }elseif($to == 'JKS'){
+ $files[] = ['name'=>'JKS 证书文件', 'file'=>'cert.jks', 'data'=>base64_encode($response)];
+ }elseif($to == 'PKCS7'){
+ $files[] = ['name'=>'PKCS7 证书文件', 'file'=>'cert.p7b', 'data'=>base64_encode($response)];
+ }
+
+ return msg('ok', 'success', ['files'=>$files]);
+
+ }catch(Exception $e){
+ return msg('error', $e->getMessage());
+ }
+ }
+
+ private function check_cert($name, $path){
+ $file_size = filesize($path);
+ if($file_size < 100 || $file_size > 50 * 1024){
+ throw new Exception($name.'文件大小超过限制');
+ }
+ }
+
+ private function check_pass($name, $value, $empty = false){
+ if($empty && empty($value)) return;
+ if(empty($value)){
+ throw new Exception($name.'不能为空');
+ }
+ if(strlen($value) < 6){
+ throw new Exception($name.'至少6个字符');
+ }
+ if(strlen($value) > 32){
+ throw new Exception($name.'最多32个字符');
+ }
+ }
+
+ private function requestApi($act, $params){
+ $requrl = self::$apiurl . '?act=' . $act;
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $requrl);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
+ $httpheader[] = "Accept: */*";
+ $httpheader[] = "Accept-Encoding: gzip,deflate,sdch";
+ $httpheader[] = "Accept-Language: zh-CN,zh;q=0.8";
+ $httpheader[] = "Connection: close";
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $httpheader);
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
+ curl_setopt($ch, CURLOPT_ENCODING, "gzip");
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ $response = curl_exec($ch);
+
+ if (curl_errno($ch) > 0) {
+ curl_close($ch);
+ throw new Exception('接口请求失败');
+ }
+
+ $httpStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+ if ($httpStatusCode != 200) {
+ curl_close($ch);
+ $arr = json_decode($response, true);
+ throw new Exception($arr ? $arr['msg'] : '接口返回数据解析失败');
+ }
+
+ curl_close($ch);
+ return $response;
+ }
+
+}
\ No newline at end of file
diff --git a/plugin/dev/cert_convert/index.html b/plugin/dev/cert_convert/index.html
new file mode 100644
index 0000000..e43a171
--- /dev/null
+++ b/plugin/dev/cert_convert/index.html
@@ -0,0 +1,327 @@
+{extend name="common/plugin_layout" /}
+{block name="title"}{$plugin.title} - {:config_get('title')}{/block}
+{block name="main"}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
工具说明
+
+
本工具支持PEM、DER、PKCS12、PKCS7、JKS等格式的证书转换
+
证书格式介绍
+
PEM:以base64的形式存放证书、私钥,常见后缀是.pem .crt .cer .key
+
DER:以二进制的形式存放证书、私钥,常见后缀是.der .crt .cer
+
PKCS#12:以二进制的形式存放证书+私钥,通常包含保护密码,常见后缀是.pfx .p12
+
PKCS#7:以树状展示证书链,也支持单个证书,不含私钥,常见后缀是.p7b .p7c .spc
+
JKS:是Java平台使用的证书存储库文件,存放证书+私钥,有密码保护,常见后缀是.jks .ks .keystore
+
+
+
+
+
+{/block}
+{block name="script"}
+
+
+
+{/block}
\ No newline at end of file
diff --git a/plugin/dev/csr/App.php b/plugin/dev/csr/App.php
new file mode 100644
index 0000000..730fef6
--- /dev/null
+++ b/plugin/dev/csr/App.php
@@ -0,0 +1,107 @@
+view();
+ }
+
+ public function query(){
+ $csr = input('post.csr');
+ if(!$csr) return msg('error','no csr');
+
+ $subject_info = openssl_csr_get_subject($csr);
+ if(!$subject_info){
+ return msg('error', 'CSR文件错误');
+ }
+
+ $pkey_detail = openssl_pkey_get_details(openssl_csr_get_public_key($csr));
+
+ $info = [
+ '通用名称(CN)' => $this->format($subject_info['CN']),
+ '国家(C)' => $this->format($subject_info['C']),
+ '省份(S)' => $this->format($subject_info['ST']),
+ '城市(L)' => $this->format($subject_info['L']),
+ '组织(O)' => $this->format($subject_info['O']),
+ '部门(OU)' => $this->format($subject_info['OU']),
+ '密钥类型' => isset(self::$key_type[$pkey_detail['type']]) ? self::$key_type[$pkey_detail['type']] : '未知',
+ '密钥强度' => $pkey_detail['bits'],
+ ];
+
+ return msg('ok','success',['info'=>$info]);
+ }
+
+ private function format($mixed){
+ if(is_array($mixed)){
+ return $mixed[array_key_first($mixed)];
+ }
+ return $mixed;
+ }
+
+ public function generate(){
+ $commonName = input('post.commonName', null, 'trim');//通用名
+ $countryName = input('post.countryName', null, 'trim');//国家
+ $stateOrProvinceName = input('post.stateOrProvinceName', null, 'trim');//省份
+ $localityName = input('post.localityName', null, 'trim');//城市
+ $organizationName = input('post.organizationName', null, 'trim');//组织
+ $organizationalUnitName = input('post.organizationalUnitName', null, 'trim');//部门
+ $subjectAltName = input('post.subjectAltName', null, 'trim');//备用名
+ $emailAddress = input('post.emailAddress', null, 'trim');//邮箱
+
+ $private_key_type = input('post.private_key_type/d');//密钥算法
+ $private_key_bits = input('post.private_key_bits/d');//密钥长度
+ $curve_name = input('post.curve_name');//曲线名称
+ $digest_alg = input('post.digest_alg');//签名算法
+ $pass_phrase = input('post.pass_phrase', null, 'trim');//私钥密码
+
+ //生成公私钥
+ $config = [
+ "private_key_bits" => $private_key_bits,
+ "private_key_type" => $private_key_type,
+ "curve_name" => $curve_name
+ ];
+ $privkey = openssl_pkey_new($config);
+ if(!$privkey){
+ return msg('error', '私钥生成失败'.openssl_error_string());
+ }
+ $privateKey = '';
+ openssl_pkey_export($privkey, $privateKey, $pass_phrase?$pass_phrase:null, $config);
+ $pubKey = openssl_pkey_get_details($privkey);
+ $publicKey = $pubKey['key'];
+
+ //生成CSR
+ $dn = array(
+ "countryName" => $countryName,
+ "stateOrProvinceName" => $stateOrProvinceName,
+ "localityName" => $localityName,
+ "organizationName" => $organizationName,
+ "organizationalUnitName" => $organizationalUnitName,
+ "commonName" => $commonName,
+ "emailAddress" => $emailAddress,
+ "subjectAltName" => $subjectAltName
+ );
+ $dn = array_filter($dn);
+ $csr = openssl_csr_new($dn, $privkey, array('digest_alg' => $digest_alg));
+ if(!$csr){
+ return msg('error', 'CSR生成失败'.openssl_error_string());
+ }
+ openssl_csr_export($csr, $csrout);
+
+ return msg('ok', 'success', ['public_key'=>$publicKey, 'private_key'=>$privateKey, 'csr'=>$csrout]);
+ }
+
+}
\ No newline at end of file
diff --git a/plugin/dev/csr/index.html b/plugin/dev/csr/index.html
new file mode 100644
index 0000000..6f4966f
--- /dev/null
+++ b/plugin/dev/csr/index.html
@@ -0,0 +1,382 @@
+{extend name="common/plugin_layout" /}
+{block name="title"}{$plugin.title} - {:config_get('title')}{/block}
+{block name="main"}
+
+
+
+
+
+
+
+
+
+
+
+
+
主题信息(以下均为选填)
+
+
密钥信息
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ | {{index}} | {{item}} |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{/block}
+{block name="script"}
+
+
+
+{/block}
\ No newline at end of file
diff --git a/plugin/dev/encrypt/index.html b/plugin/dev/encrypt/index.html
index 16025d2..a440dfc 100644
--- a/plugin/dev/encrypt/index.html
+++ b/plugin/dev/encrypt/index.html
@@ -11,45 +11,45 @@
+
-
-
+
解密
-
+
交换
-
+
清空
@@ -57,7 +57,7 @@
@@ -66,44 +66,98 @@
{/block}
{block name="script"}
+
+
{/block}
\ No newline at end of file
diff --git a/plugin/dev/guomi/App.php b/plugin/dev/guomi/App.php
new file mode 100644
index 0000000..df341f0
--- /dev/null
+++ b/plugin/dev/guomi/App.php
@@ -0,0 +1,53 @@
+view();
+ }
+
+ public function output()
+ {
+ $type = input('post.type/d');
+ if($type == 1){
+ $cert = input('post.cert');
+ $pkey_res = openssl_pkey_get_public($cert);
+ if(!$pkey_res){
+ return msg('error', '导出失败,公钥证书不正确');
+ }
+ $pkey_detail = openssl_pkey_get_details($pkey_res);
+ $pkey_hex = bin2hex($this->pem2der($pkey_detail['key']));
+ if(strlen($pkey_hex) > 130) $pkey_hex = substr($pkey_hex, -130);
+ return msg('ok', '导出成功', $pkey_hex);
+ }elseif($type == 2){
+ $csr = input('post.csr');
+ $pkey_res = openssl_csr_get_public_key($csr);
+ if(!$pkey_res){
+ return msg('error', '导出失败,CSR不正确');
+ }
+ $pkey_detail = openssl_pkey_get_details($pkey_res);
+ $pkey_hex = bin2hex($this->pem2der($pkey_detail['key']));
+ if(strlen($pkey_hex) > 130) $pkey_hex = substr($pkey_hex, -130);
+ return msg('ok', '导出成功', $pkey_hex);
+ }
+ }
+
+ private function pem2der($pem_data)
+ {
+ $begin = "-----";
+ $end = "-----END";
+ $pem_data = substr($pem_data, strpos($pem_data, $begin, 6) + strlen($begin));
+ $pem_data = substr($pem_data, 0, strpos($pem_data, $end));
+ $der = base64_decode($pem_data);
+ return $der;
+ }
+}
\ No newline at end of file
diff --git a/plugin/dev/guomi/index.html b/plugin/dev/guomi/index.html
new file mode 100644
index 0000000..c2e2c11
--- /dev/null
+++ b/plugin/dev/guomi/index.html
@@ -0,0 +1,478 @@
+{extend name="common/plugin_layout" /}
+{block name="title"}{$plugin.title} - {:config_get('title')}{/block}
+{block name="main"}
+
+
+
+
+
+
+
+
+
+
+
+ 生成
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 加密
+
+
+
+
+ 解密
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 签名
+
+
+
+
+ 验签
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 验证
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 导出
+
+
+
+
+
+
+
+
+
+
+
+ 压缩
+
+
+
+
+ 还原
+
+
+
+
+
+
+
+
+
+{/block}
+{block name="script"}
+
+
+
+
+
+{/block}
\ No newline at end of file
diff --git a/plugin/dev/rsa/App.php b/plugin/dev/rsa/App.php
index bb8b005..a10a9fd 100644
--- a/plugin/dev/rsa/App.php
+++ b/plugin/dev/rsa/App.php
@@ -19,6 +19,7 @@ class App extends Plugin
"private_key_bits" => 1024,
//选择在创建CSR时应该使用哪些扩展。可选值有 OPENSSL_KEYTYPE_DSA, OPENSSL_KEYTYPE_DH, OPENSSL_KEYTYPE_RSA 或 OPENSSL_KEYTYPE_EC. 默认值是 OPENSSL_KEYTYPE_RSA.
"private_key_type" => OPENSSL_KEYTYPE_RSA,
+ "curve_name" => ''
];
private $passPhrase;
private $rsaPrivateKey;
@@ -28,6 +29,7 @@ class App extends Plugin
private $origin;
private $coded;
private $opensslPadding;
+ private $opensslAlgo = 1;
public function __construct()
@@ -35,13 +37,16 @@ class App extends Plugin
$this->passPhrase = request()->param("pass_phrase");
if($this->passPhrase == '') $this->passPhrase = null;
$this->rsaPrivateKey = request()->param("private_key");
- $this->rsaPublicKey = request()->param("public_key");
- $this->config["private_key_bits"] = request()->param("private_key_bits");
+ $this->rsaPublicKey = $this->getPemKey(request()->param("public_key"), 'PUBLIC KEY');
+ $this->config["private_key_type"] = request()->param("private_key_type/d");
+ $this->config["private_key_bits"] = request()->param("private_key_bits/d");
+ $this->config["curve_name"] = request()->param("curve_name");
$this->data = request()->param("data");
$this->origin = request()->param("origin");
$this->coded = request()->param("coded");
$this->sign = request()->param("sign");
$this->opensslPadding = request()->param("openssl_padding");
+ $this->opensslAlgo = intval(request()->param("openssl_algo"));
}
public function index()
@@ -179,7 +184,7 @@ class App extends Plugin
public function sign()
{
try {
- if (openssl_sign($this->data, $ret, $this->getRsaPrivateKey())) {
+ if (openssl_sign($this->data, $ret, $this->getRsaPrivateKey(), $this->opensslAlgo)) {
$ret = base64_encode($ret);
return msg('ok', 'success', $ret);
}
@@ -203,7 +208,7 @@ class App extends Plugin
$ret = false;
$sign = base64_decode($this->sign);
if ($sign !== false) {
- if (openssl_verify($this->data, $sign, $this->rsaPublicKey) === 1) {
+ if (openssl_verify($this->data, $sign, $this->rsaPublicKey, $this->opensslAlgo) === 1) {
$ret = true;
}
}
@@ -231,7 +236,25 @@ class App extends Plugin
public function output()
{
+ $type = input('post.type/d');
try {
+ if($type == 1){
+ $cert = input('post.cert');
+ $pkey_res = openssl_pkey_get_public($cert);
+ if(!$pkey_res){
+ return msg('error', '导出失败,公钥证书不正确');
+ }
+ $pkey_detail = openssl_pkey_get_details($pkey_res);
+ return msg('ok', '导出成功', $pkey_detail['key']);
+ }elseif($type == 2){
+ $csr = input('post.csr');
+ $pkey_res = openssl_csr_get_public_key($csr);
+ if(!$pkey_res){
+ return msg('error', '导出失败,CSR不正确');
+ }
+ $pkey_detail = openssl_pkey_get_details($pkey_res);
+ return msg('ok', '导出成功', $pkey_detail['key']);
+ }
$openssl_pkey_get_details = openssl_pkey_get_details($this->getRsaPrivateKey());
if ($openssl_pkey_get_details && !empty($openssl_pkey_get_details['key'])) {
return msg('ok', '导出成功', $openssl_pkey_get_details['key']);
@@ -242,15 +265,47 @@ class App extends Plugin
}
}
+ public function key_encrypt()
+ {
+ try {
+ $privateKey = openssl_pkey_get_private($this->getPemKey($this->rsaPrivateKey, 'PRIVATE KEY'));
+ if ($privateKey === false) {
+ throw new \Exception('私钥不正确或已被加密');
+ }
+ openssl_pkey_export($privateKey, $encrypted, $this->passPhrase);
+ return msg('ok', '加密成功', $encrypted);
+ } catch (\Exception $e) {
+ return msg('error', $e->getMessage());
+ }
+ }
+
+ public function key_decrypt()
+ {
+ try {
+ openssl_pkey_export($this->getRsaPrivateKey(), $decrypted);
+ return msg('ok', '解密成功', $decrypted);
+ } catch (\Exception $e) {
+ return msg('error', $e->getMessage());
+ }
+ }
+
/**
* @return array|mixed|null
*/
public function getRsaPrivateKey()
{
- $privateKey = openssl_pkey_get_private($this->rsaPrivateKey, $this->passPhrase);
+ $privateKey = openssl_pkey_get_private($this->getPemKey($this->rsaPrivateKey, $this->passPhrase ? 'ENCRYPTED PRIVATE KEY' : 'PRIVATE KEY'), $this->passPhrase);
if ($privateKey === false) {
throw new \Exception('私钥不正确或密码错误');
}
return $privateKey;
}
+
+ private function getPemKey($str, $type){
+ if(empty($str) || strpos($str, '-----BEGIN')!==false) return $str;
+ $pem = "-----BEGIN ".$type."-----\n" .
+ wordwrap($str, 64, "\n", true) .
+ "\n-----END ".$type."-----";
+ return $pem;
+ }
}
\ No newline at end of file
diff --git a/plugin/dev/rsa/index.html b/plugin/dev/rsa/index.html
index d6416df..29f3932 100644
--- a/plugin/dev/rsa/index.html
+++ b/plugin/dev/rsa/index.html
@@ -6,21 +6,34 @@
-
+
+
+
+
+
+
+
+
+
@@ -61,12 +81,6 @@
-
-