关于前后台rsa加解密算法 -- 后台篇

一、生成密钥

1. 生成私钥

openssl genrsa -out rsa_private_key.pem 1024

2. 生成公钥

openssl rsa -pubout -in rsa_private_key.pem -out rsa_public_key.pem

二、 用PHP实现RSA加密,解密,加签,验签

php内置了很丰富的openssl方法,需要安装php的openssl扩展,方法百度,至于查看,就phpinfo()后查看有没有openssl,操作类如下

<?php
declare(strict_types = 1);

/**
 *  RAS加解密类
 * 
 *  用于实现RSA加密,解密,加签,验签
 *  
 *  @author alex.xu <xux851@gmail.com>
 *  @version 1.0.0
 *  
 */

class Rsa
{
  /** 私钥 **/
  private $_privateKey;

  /** 公钥 **/
  private $_publicKey;

  /** 密钥的存储路径 **/
  private $_keyPath;

  public function __construct(string $path) {
    if (empty($path) || !is_dir($path)) throw new \Exception('必须设置密钥的存储路径');
    // 设置私钥
    $this->_keyPath = $path;
    $file = $this->_keyPath . DIRECTORY_SEPARATOR . 'rsa_private_key.pem';
    $prk = file_get_contents($file);
    $this->_privateKey = openssl_pkey_get_private($prk);
    // 设置公钥
    $file = $this->_keyPath . DIRECTORY_SEPARATOR . 'rsa_public_key.pem';
    $puk = file_get_contents($file);
    $this->_publicKey = openssl_pkey_get_public($puk);
  }

  /** 设置私钥 */
  public function setPrivateKey() {
    if (is_resource($this->_privateKey)) return true;
    $file = $this->_keyPath . DIRECTORY_SEPARATOR . 'rsa_private_key.pem';
    $prk = file_get_contents($file);
    $this->_privateKey = openssl_pkey_get_private($prk);
    return true;
  }

  /** 设置公钥 */
  public function setPublicKey() {
    if (is_resource($this->_publicKey)) return true;
    $file = $this->_keyPath . DIRECTORY_SEPARATOR . 'rsa_public_key.pem';
    $puk = file_get_contents($file);
    $this->_publicKey = openssl_pkey_get_public($puk);
    return true;
  }

  /**
   * 加密
   * 
   * @param string $data 要加密的字符串 
   * @param integer $type   类型 0. 私钥 1. 公钥
   * @return string|null
   * 
   */
  public function Encrypt(string $data = '', int $type = 0) {
    if (empty($data)) return null;
    $r = $type == 0 ? openssl_private_encrypt($data, $encrypted, $this->_privateKey) : openssl_public_encrypt($data, $encrypted, $this->_publicKey);
    return $r ? base64_encode($encrypted) : null;
  }

  /**
   * 解密
   * 
   * @param string $data   要解密的字符串 
   * @param integer $type  类型 0. 私钥 1. 公钥
   * @return string|null
   * 
   */
  public function Decrypt(string $encrypted = '', int $type = 0) {
    if (empty($encrypted)) return null; 
    $encrypted = base64_decode($encrypted);
    $r = $type == 0 ? openssl_private_decrypt($encrypted, $decrypted, $this->_privateKey) : openssl_public_decrypt($encrypted, $decrypted, $this->_publicKey);
    return $r ? $decrypted : null;
  }

  /**
   * 私钥加签
   * 
   * @param string $data 要加签的串
   * @return string|null
   * 
   */
  public function sign(string $data = '') {
    if (empty($data)) return null;
    openssl_sign($data, $sign, $this->_privateKey);
    $sign = base64_encode($sign);
    return $sign;
  }

  /**
   * 公钥验签
   * 
   * @param string $data 加密串
   * @param string $sign 上一步的验名
   * @return bool|null
   * 
   */
  public function verify(string $data = '', string $sign = '') {
    if (empty($data)) return null;
    return !!openssl_verify($data, base64_decode($sign), $this->_publicKey);
  }

  /** 释放资源 */
  public function __destruct() {
    $this->_privateKey ?? openssl_free_key($this->_privateKey);
    $this->_publicKey ?? openssl_free_key($this->_publicKey);
  }
}

三、使用方法

将生成的2个文件放在同目录中

$RSA = new Rsa(dirname(__FILE__));

// 公钥加密 --> 私钥加密

$string = 'del.pub';

$publicString = $RSA->Encrypt($string, 1);
echo '公钥加密后:' . $publicString . PHP_EOL;

$privateString = $RSA->Decrypt($publicString);
echo '私钥解密后:' . $privateString . PHP_EOL;

// 私钥加签 --> 公钥验签
$sign = $RSA->sign($string);
echo '私钥加签后:' . $sign . PHP_EOL;
$result = $RSA->verify($string, $sign);
echo '验证签名是否正确:' . (string)$result;

结果如下:

php Rsa.php
公钥加密后:aFDWf858bi30qnyxQvaVz4vTe4Q4+7OU4p+MkQNA8qtPKGxeh11MvRhdq5udzfQPRi72wyrMkfFnWTs5OTh6fXKA3JJPJyezs0yoEIRDfZDJz0sJKPSrZcU5TpCnnU0F3vjIZjxmQFJmSw3OCzGwlQAecAPdpxmUQgg2kl8yg4M=
私钥解密后:del.pub
私钥加签后:MHXPOJm2J6E/NW9n15q5p+uVZhIeUYZ2t8CauIEGR64bToQ+1m5LKKaN+hpaP0Odc7uG8z8JEVTiAsoWrOuxRF17OiKOYzyCmyU9nD4t8irMvmLmTUdX3Pin1iKXrn8SBj7y466EpENDiBkICcViYNTUf/JgrEs7Gn5YcBm+3HU=
验证签名是否正确:1
最后修改于:2021年04月28日 00:25

仅有一条评论

  1. hhh hhh

    666大佬

添加新评论

* 鉴于国内大环境,评论需要审核才能放出,请不要多次重复提交!