OpenSSL 公鑰私鑰加解密封裝

一念滄海一念桑田發表於2019-06-22
<?php
/**
 * OpenSSL 非對稱加解密
 *
 * Class Signature
 * @package utils
 */
class Signature
{

    /**
     * 建立公鑰私鑰配置
     *
     * @var array
     */
    protected $createConfig = [
        'config' => 'D:\phpStudy\PHPTutorial\Apache\conf\openssl.cnf',//openssl配置檔案路徑,使用的時候再具體配置
        'digest_alg' => 'sha512',
        'private_key_bits' => 1024, //位元組數    512 1024  2048   4096 等
        'private_key_type' => OPENSSL_KEYTYPE_RSA, //加密型別
    ];

    /**
     * 基本配置
     *
     * @var array
     */
    protected $config = [
        'private_key' => '',//私鑰pem檔案路徑 例如: /var/www/test/app/ssh/private_key.pem
        'public_key' => '',//公鑰pem檔案路徑 例如:/var/www/test/app/ssh/rsa_public_key.pem
    ];

    /**
     * 公鑰
     *
     * @var string
     */
    protected $privateKey = '';

    /**
     * 私鑰
     *
     * @var string
     */
    protected $publicKey = '';

    /**
     * Signature constructor.
     * @param array $config
     */
    public function __construct(array $config = [])
    {
        if ($config){
            $this->setConfig($config);
        }
    }

    /**
     * 設定配置
     *
     * @Author: kanin <990921093@qq.com>
     * @Date: 2019/06/21 15:42
     * @param $config
     * @return $this
     */
    public function setConfig($config)
    {
        $this->config = array_merge($this->config, $config);

        //私鑰
        if (is_file($this->config['private_key'])) {
            $this->privateKey = file_get_contents($this->config['private_key']);
        }
        //公鑰
        if (is_file($this->config['public_key'])) {
            $this->publicKey = file_get_contents($this->config['public_key']);
        }
        return $this;
    }

    /**
     * 建立私鑰和公鑰
     *
     * @Author: kanin <990921093@qq.com>
     * @Date: 2019/06/21 15:53
     * @param string $path
     * @return array
     * @throws \Exception
     */
    public function createKey($path = '')
    {
        if (!$path) {
            $path = $this->config['path'];
        }

        try {
            //建立公鑰和私鑰   返回資源
            $res = openssl_pkey_new($this->createConfig);

            //從得到的資源中獲取私鑰,把私鑰賦給$privateKey
            openssl_pkey_export($res, $privateKey, null, $this->createConfig);

            //從得到的資源中獲取公鑰,返回公鑰$pubKey
            $pubKey = openssl_pkey_get_details($res);

            //公鑰
            $publicKey = $pubKey["key"];

            //生成檔案
            $publicKeyPath = $path . 'rsa_public_key.pem';

            $privateKeyPath = $path . 'private_key.pem';

            if (!is_dir($path)) {
                mkdir($path);
            }

            file_put_contents($publicKeyPath, $publicKey);

            file_put_contents($privateKeyPath, $privateKey);

        } catch (\Exception $exception) {

            throw new \Exception($exception->getMessage(), 1001);

        }

        return compact('publicKeyPath', 'privateKeyPath');
    }

    /**
     * 私鑰加密
     *
     * @Author: kanin <990921093@qq.com>
     * @Date: 2019/06/21 15:21
     * @param $data
     * @return string
     * @throws \Exception
     */
    public function privateKeyEncrypt(string $data)
    {
        if (!$this->privateKey) {
            throw new \Exception('私鑰未設定', 1002);
        }

        //使用私鑰加密
        openssl_private_encrypt($data, $encrypted, $this->privateKey);

        //加密後通常都會有一些特殊字元,需要用base64_encode處理一下

        return base64_encode($encrypted);
    }

    /**
     * 公鑰加密
     *
     * @Author: kanin <990921093@qq.com>
     * @Date: 2019/06/21 15:42
     * @param $data
     * @return string
     * @throws \Exception
     */
    public function publicKeyEncrypt(string $data)
    {
        if (!$this->publicKey) {
            throw new \Exception('公鑰未設定', 1003);
        }

        //使用公鑰加密
        openssl_public_encrypt($data, $encrypted, $this->publicKey);

        //加密後通常都會有一些特殊字元,需要用base64_encode處理一下
        return base64_encode($encrypted);
    }

    /**
     * 私鑰解密
     *
     * @Author: kanin <990921093@qq.com>
     * @Date: 2019/06/21 15:23
     * @param $data
     * @return bool|string
     * @throws \Exception
     */
    public function privateKeyDecrypt(string $data)
    {
        if (!$this->privateKey) {
            throw new \Exception('私鑰未設定', 1002);
        }

        //加密的時候使用了base64處理
        $data = base64_decode($data);

        //使用私鑰解密
        openssl_private_decrypt($data, $decrypted, $this->privateKey);

        return $decrypted;
    }

    /**
     * 公鑰解密
     *
     * @Author: kanin <990921093@qq.com>
     * @Date: 2019/06/21 15:25
     * @param $data
     * @return bool|string
     * @throws \Exception
     */
    public function publicKeyDecrypt(string $data)
    {
        if (!$this->publicKey) {
            throw new \Exception('公鑰未設定', 1003);
        }

        //加密的時候使用了base64處理
        $data = base64_decode($data);

        //使用公鑰解密
        openssl_public_decrypt($data, $decrypted, $this->publicKey);

        return $decrypted;
    }
}

使用

       $config = [
            'private_key'=>'/var/www/test/app/ssh/private_key.pem',
            'public_key'=>'/var/www/test/app/ssh/rsa_public_key.pem',
        ];

        $string = '測試';
        $signature = new  Signature($config);

        $encrypted = $signature->publicKeyEncrypt($string);
        $decrypted = $signature->privateKeyDecrypt($encrypted);

        var_dump("公鑰加密:".$encrypted);
        var_dump("私鑰解密:".$decrypted);
        echo "------------------";

        $encrypted = $signature->privateKeyEncrypt($string);
        $decrypted = $signature->publicKeyDecrypt($encrypted);

        var_dump("私鑰加密:".$encrypted);
        var_dump("公鑰解密:".$decrypted);
本作品採用《CC 協議》,轉載必須註明作者和本文連結
每天進步一點點,多年以後再回頭,就會發現自己不知不覺走了很遠很遠

相關文章