PHP下的RSA对称加解密 根证书自签与签发子证书

<?php
namespace app\test\controller;
use app\test\Test;

class Rsa extends Test {
    protected $public_key='-----BEGIN PUBLIC KEY-----
your public key here...
-----END PUBLIC KEY-----';
    protected $private_key='-----BEGIN PRIVATE KEY-----
your private key here...
-----END PRIVATE KEY-----';
    public function index(){
	    echo <<<html
	    <a href="/test/rsa/root" target="_blank">ROOT根证书自签</a><br>
	    <a href="/test/rsa/sub" target="_blank">根证书与子证书加密解密</a><br>
	    <a href="/test/rsa/cert" target="_blank">签发子证书</a><br>
	    <a href="/test/rsa/javascript" target="_blank">JS版RSA加密解密demo</a><br>
	    <a href="/test/rsa/largeRsa" target="_blank">RSA分段加解密PHPdemo</a><br>
html;
    }
	public function root() {
	    echo "<h2><pre>";
        $config = array(
            "countryName" => "CN",
            "stateOrProvinceName" => "ChongQing",
            "localityName" => "ChongQing",
            "organizationName" => "Hamm Root Certificate Authority",
            "organizationalUnitName" => "Hamm Root CA",
            "commonName" => "Hamm.cn",
            "emailAddress" => "admin@hamm.cn"
        );
        $private = openssl_pkey_new(array(
            "private_key_bits" => 2048,
            "private_key_type" => OPENSSL_KEYTYPE_RSA,
        ));
        $public = openssl_pkey_get_details($private);
        $public_key = $public['key'];
        
        $csr = openssl_csr_new($config, $private, array('digest_alg' => 'sha256'));
        $x509 = openssl_csr_sign($csr, null, $private, $days=36500, array('digest_alg' => 'sha256'));
        openssl_csr_export($csr, $csrout);
        openssl_x509_export($x509, $certout);
        openssl_pkey_export($private, $private_key);
        $rsa=["cert"=>$certout,"private"=>$private_key,"public"=>$public_key];
        print_r($rsa);
        $private_key = openssl_pkey_get_private($private_key);
        $public_key = openssl_pkey_get_public($public_key);
        echo "<h2><hr>";
        $str_1 = "Hello World!";
        echo "<h2><br>源数据:</h2>".$str_1."<hr>";
        
        openssl_private_encrypt($str_1, $str_2, $private_key);
        echo "<h2>私钥加密后:</h2>".base64_encode($str_2)."<hr>";
        openssl_public_decrypt($str_2, $str_3, $public_key);
        echo "<h2>公钥解密后:</h2>".$str_3."<hr>";
        
        
        openssl_public_encrypt($str_1, $str_2, $public_key);
        echo "<h2>公钥加密后:</h2>".base64_encode($str_2)."<hr>";
        openssl_private_decrypt($str_2, $str_3, $private_key);
        echo "<h2>私钥解密后:</h2>".$str_3."<hr>";
         
	}
	public function sub(){
	    echo <<<html
	    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>测试</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <meta name="format-detection" content="telephone=no" />
        <meta name="apple-mobile-web-app-capable" content="yes" />
        <meta name="apple-mobile-web-app-status-bar-style" content="black">
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <link rel="stylesheet" href="/static/weui/0.4.3/style/weui.min.css">
        <link rel="stylesheet" href="/static/jquery-weui/0.8.2/css/jquery-weui.min.css">
        <link rel="stylesheet" href="//at.alicdn.com/t/font_666204_6s0kgt126smdkj4i.css"  media="all">
        <style>
        body, html{
            margin:0;
            padding:20px;
            display:inline-block;
            word-break:break-word;
        }
        hr{
            margin-bottom:50px;
        }
        </style>
html;

        $config = array(
            "countryName" => "CN",
            "stateOrProvinceName" => "sub_cert_test",
            "localityName"  => "sub_cert_test",
            "organizationName"  => "sub_cert_test",
            "organizationalUnitName"  => "sub_cert_test",
            "commonName" => "sub_cert_test",
            "emailAddress"  => "sub_cert_test"
        );
        $private_sub = openssl_pkey_new(array(
            "private_key_bits" => 2048,
            "private_key_type" => OPENSSL_KEYTYPE_RSA,
        ));
        
        $public_sub = openssl_pkey_get_details($private_sub);
        $public_key_sub = $public_sub['key'];
        
        $csr = openssl_csr_new($config, $private, array('digest_alg' => 'sha256'));
        $x509 = openssl_csr_sign($csr,file_get_contents("./certs/root.crt"), [file_get_contents("./certs/root.key"),''], 3650);
        // openssl_csr_export($csr, $csrout);
        // openssl_x509_export($x509, $cert_sub);
        openssl_pkey_export($private_sub, $private_key_sub);
        
        $str_1 = "Hello World";
        echo "<h2>源数据串:</h2>".($str_1)."<hr>";
        
        $private_key_sub = openssl_pkey_get_private($private_key_sub);
        $public_key_sub = openssl_pkey_get_public($public_key_sub);
        
        $private_key = openssl_pkey_get_private(file_get_contents("./certs/root.key"));
        $public_key = openssl_pkey_get_public(file_get_contents("./certs/root.pub"));
        
        
        openssl_public_encrypt($str_1, $str_2, $public_key_sub);
        echo "<h2>子 公钥加密后:</h2>".base64_encode($str_2)."<hr>";
        openssl_private_decrypt($str_2, $str_3, $private_key_sub);
        echo "<h2>子 私钥解密后:</h2>".$str_3."<hr>";
        openssl_private_decrypt($str_2, $str_3, $private_key);
        echo "<h2>根 私钥解密后:</h2>".$str_3."<hr>";
        
        
        openssl_private_encrypt($str_1, $str_2, $private_key_sub);
        echo "<h2>子 私钥加密后:</h2>".base64_encode($str_2)."<hr>";
        openssl_public_decrypt($str_2, $str_3, $public_key_sub);
        echo "<h2>子 公钥解密后:</h2>".$str_3."<hr>";
        openssl_public_decrypt($str_2, $str_3, $public_key);
        echo "<h2>根 公钥解密后:</h2>".$str_3."<hr>";
        
        
        openssl_public_encrypt($str_1, $str_2, $public_key);
        echo "<h2>根 公钥加密后:</h2>".base64_encode($str_2)."<hr>";
        openssl_private_decrypt($str_2, $str_3, $private_key);
        echo "<h2>根 私钥解密后:</h2>".$str_3."<hr>";
        openssl_private_decrypt($str_2, $str_3, $private_key_sub);
        echo "<h2>子 私钥解密后:</h2>".$str_3."<hr>";
        
        
        openssl_private_encrypt($str_1, $str_2, $private_key);
        echo "<h2>根 私钥加密后:</h2>".base64_encode($str_2)."<hr>";
        openssl_public_decrypt($str_2, $str_3, $public_key);
        echo "<h2>根 公钥解密后:</h2>".$str_3."<hr>";
        openssl_public_decrypt($str_2, $str_3, $public_key_sub);
        echo "<h2>子 公钥解密后:</h2>".$str_3."<hr>";
        
        echo <<<html
</body>
</html>
html;
        
        
        
	}
	public function javascript(){
	    return $this->show();
	}
	public function cert() {
        if($this->request->isPost()){
            header("Content-type:application/x-x509-ca-cert");
            header("Content-Disposition:attachment;filename=sub.crt");
            $config = array(
                "countryName" => "CN",
                "stateOrProvinceName" => empty($_REQUEST['province'])?"sub_cert_test":urldecode($_REQUEST['province']),
                "localityName" => empty($_REQUEST['city'])?"sub_cert_test":urldecode($_REQUEST['city']),
                "organizationName" => empty($_REQUEST['orgname'])?"sub_cert_test":urldecode($_REQUEST['orgname']),
                "organizationalUnitName" => empty($_REQUEST['depart'])?"sub_cert_test":urldecode($_REQUEST['depart']),
                "commonName" => empty($_REQUEST['username'])?"sub_cert_test":urldecode($_REQUEST['username']),
                "emailAddress" => empty($_REQUEST['email'])?"admin@hamm.cn":urldecode($_REQUEST['email'])
            );
            $private = openssl_pkey_new(array(
                "private_key_bits" => 2048,
                "private_key_type" => OPENSSL_KEYTYPE_RSA,
            ));
            
            $public = openssl_pkey_get_details($private);
            $public_key = $public['key'];
            
            $csr = openssl_csr_new($config, $private, array('digest_alg' => 'sha256'));
            $x509 = openssl_csr_sign($csr,file_get_contents("./certs/root.crt"), [file_get_contents("./certs/root.key"),''], 3650);
            openssl_csr_export($csr, $csrout);
            openssl_x509_export($x509, $certout);
            openssl_pkey_export($private, $private_key);
            
            print_r($certout."\n\n\n".$public_key."\n\n\n".$private_key);
            die;
        }else{
            echo <<<____
<style>
input{
    border:1px solid #ddd;
    padding:10px 20px;
    font-size:16px;
    margin:5px;
}
</style>
<form action="" method="POST" style="width:100%;text-align:left;">
<span style="width:120px;display:inline-block;">NAME:</span><input type="text" name="username" placeholder="Your name"/><br>
<span style="width:120px;display:inline-block;">EMAIL:</span><input type="text" name="email" placeholder="Your email" value="test@test.com"/><br>
<span style="width:120px;display:inline-block;">ORGNAME:</span><input type="text" name="orgname" placeholder="Your orgname" value="Group"/><br>
<span style="width:120px;display:inline-block;">DEPART:</span><input type="text" name="depart" placeholder="Your depart" value="IT depart"/><br>
<span style="width:120px;display:inline-block;">PROVINCE:</span><input type="text" name="province" placeholder="Your province" value="Beijing"/><br>
<span style="width:120px;display:inline-block;">CITY:</span><input type="text" name="city" placeholder="Your city" value="haidian"/><br>
<input type="submit" value="To sign a Cert">
</form>
____;
        }
	}
	public function largeRsa(){
        $private_key=$this->private_key;
        $private_key = openssl_pkey_get_private($private_key);
        
        $public_key=$this->public_key;
        $public_key = openssl_pkey_get_public($public_key);
        
        $data_source = 'Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!Hello World!';
        
        echo "<br>源数据:<br>".$data_source."<hr>";
        
        //私钥加密
        $data_encode = $this->rsa_encode_private($data_source,$private_key);
        echo "私钥加密后:<br>".$data_encode."<hr>";
        //公钥解密
        $data_decode = $this->rsa_decode_public($data_encode,$public_key);
        echo "公钥解密后:<br>".$data_decode."<hr>";
        //校验结果
        if($data_source === $data_decode){
            echo "<h1>公钥解密成功</h1>";
        }else{
            echo "<h1>公钥解密失败</h1>";
        }
        
        //公钥加密
        $data_encode = $this->rsa_encode_public($data_source,$public_key);
        echo "公钥加密后:<br>".$data_encode."<hr>";
        //私钥解密
        $data_decode = $this->rsa_decode_private($data_encode,$private_key);
        echo "私钥解密后:<br>".$data_decode."<hr>";
        //校验结果
        if($data_source === $data_decode){
            echo "<h1>私钥解密成功</h1>";
        }else{
            echo "<h1>私钥解密失败</h1>";
        }
	}
	
    //私钥加密方法
    protected function rsa_encode_private($data,$private_key,$length_break = 128){
        $index = 0;
        $result='';
        if($length_break > 1024){
            $length_break = 1024;
        }
        while(true){
            $temp = substr($data,$index,$length_break);
            if(strlen($temp)==0 || $index>=strlen($data)-1){
                break;
            }
            openssl_private_encrypt($temp, $temp, $private_key);
            $temp = base64_encode($temp);
            $result .= "\n". $temp;
            $index += $length_break;
        }
        return $result;
    }
    //公钥解密方法
    protected function rsa_decode_public($data,$public_key,$line_key = "\n"){
        $index = 0;
        $result='';
        $arr = explode("\n",$data);
        foreach($arr as $temp){
            if(empty($temp)){
                continue;
            }
            openssl_public_decrypt(base64_decode($temp), $temp, $public_key);
            $result .= $temp;
        }
        return $result;
    }
    
    //公钥加密方法
    protected function rsa_encode_public($data,$public_key,$length_break = 128){
        $index = 0;
        $result='';
        if($length_break > 1024){
            $length_break = 1024;
        }
        while(true){
            $temp = substr($data,$index,$length_break);
            if(strlen($temp)==0 || $index>=strlen($data)-1){
                break;
            }
            openssl_public_encrypt($temp, $temp, $public_key);
            $temp = base64_encode($temp);
            $result .= "\n". $temp;
            $index += $length_break;
        }
        return $result;
    }
    
    //私钥解密方法
    protected function rsa_decode_private($data,$private_key,$line_key = "\n"){
        $index = 0;
        $result='';
        $arr = explode("\n",$data);
        foreach($arr as $temp){
            if(empty($temp)){
                continue;
            }
            openssl_private_decrypt(base64_decode($temp), $temp, $private_key);
            $result .= $temp;
        }
        return $result;
    }
}