PHP的RSA加密解密方法以及开发接口使用

网络安全问题很重要,尤其是保证数据安全,遇到很多在写接口的程序员直接都是明文数据传输,在我看来这是很不专业的。本人提倡经过接口的数据都要进行加密解密之后进行使用。

这篇文章主要介绍使用PHP开发接口,数据实现RSA加密解密后使用,实例分析了PHP自定义RSA类实现加密与解密的技巧,非常具有实用价值,需要的朋友可以参考下。

简单介绍RSA

RSA加密算法是最常用的非对称加密算法,CFCA在证书服务中离不了它。但是有不少新手对它不太了解。下面仅作简要介绍。RSA是第一个比较完善的公开密钥算法,它既能用于加密,也能用于数字签名。RSA以它的三个发明者Ron Rivest, Adi Shamir, Leonard Adleman的名字首字母命名,这个算法经受住了多年深入的密码分析,虽然密码分析者既不能证明也不能否定RSA的安全性,但这恰恰说明该算法有一定的可信性,目前它已经成为最流行的公开密钥算法。RSA的安全基于大数分解的难度。其公钥和私钥是一对大素数(100到200位十进制数或更大)的函数。从一个公钥和密文恢复出明文的难度,等价于分解两个大素数之积(这是公认的数学难题)。

下面为具体类、实例:

<?php 

/**
 * RSA算法类
 * 签名及密文编码:base64字符串/十六进制字符串/二进制字符串流
 * 填充方式: PKCS1Padding(加解密)/NOPadding(解密)
 *
 * Notice:Only accepts a single block. Block size is equal to the RSA key size!
 * 如密钥长度为1024 bit,则加密时数据需小于128字节,加上PKCS1Padding本身的11字节信息,所以明文需小于117字节
 *
 * @author: ZHIHUA_WEI
 * @version: 1.0.0
 * @date: 2017/06/30
 */
class RSA
{
  private $pubKey = null;
  private $priKey = null; 

  /**
   * 构造函数
   *
   * @param string 公钥文件(验签和加密时传入)
   * @param string 私钥文件(签名和解密时传入)
   */
  public function __construct($public_key_file = '', $private_key_file = '')
  {
    if ($public_key_file) {
      $this->_getPublicKey($public_key_file);
    }
    if ($private_key_file) {
      $this->_getPrivateKey($private_key_file);
    }
  } 

  // 私有方法
  /**
   * 自定义错误处理
   */
  private function _error($msg)
  {
    die('RSA Error:' . $msg); //TODO
  } 

  /**
   * 检测填充类型
   * 加密只支持PKCS1_PADDING
   * 解密支持PKCS1_PADDING和NO_PADDING
   *
   * @param int 填充模式
   * @param string 加密en/解密de
   * @return bool
   */
  private function _checkPadding($padding, $type)
  {
    if ($type == 'en') {
      switch ($padding) {
        case OPENSSL_PKCS1_PADDING:
          $ret = true;
          break;
        default:
          $ret = false;
      }
    } else {
      switch ($padding) {
        case OPENSSL_PKCS1_PADDING:
        case OPENSSL_NO_PADDING:
          $ret = true;
          break;
        default:
          $ret = false;
      }
    }
    return $ret;
  } 

  private function _encode($data, $code)
  {
    switch (strtolower($code)) {
      case 'base64':
        $data = base64_encode('' . $data);
        break;
      case 'hex':
        $data = bin2hex($data);
        break;
      case 'bin':
      default:
    }
    return $data;
  } 

  private function _decode($data, $code)
  {
    switch (strtolower($code)) {
      case 'base64':
        $data = base64_decode($data);
        break;
      case 'hex':
        $data = $this->_hex2bin($data);
        break;
      case 'bin':
      default:
    }
    return $data;
  } 

  private function _getPublicKey($file)
  {
    $key_content = $this->_readFile($file);
    if ($key_content) {
      $this->pubKey = openssl_get_publickey($key_content);
    }
  } 

  private function _getPrivateKey($file)
  {
    $key_content = $this->_readFile($file);
    if ($key_content) {
      $this->priKey = openssl_get_privatekey($key_content);
    }
  } 

  private function _readFile($file)
  {
    $ret = false;
    if (!file_exists($file)) {
      $this->_error("The file {$file} is not exists");
    } else {
      $ret = file_get_contents($file);
    }
    return $ret;
  } 

  private function _hex2bin($hex = false)
  {
    $ret = $hex !== false && preg_match('/^[0-9a-fA-F]+$/i', $hex) ? pack("H*", $hex) : false;
    return $ret;
  } 

  /**
   * 生成签名
   *
   * @param string 签名材料
   * @param string 签名编码(base64/hex/bin)
   * @return 签名值
   */
  public function sign($data, $code = 'base64')
  {
    $ret = false;
    if (openssl_sign($data, $ret, $this->priKey)) {
      $ret = $this->_encode($ret, $code);
    }
    return $ret;
  } 

  /**
   * 验证签名
   *
   * @param string 签名材料
   * @param string 签名值
   * @param string 签名编码(base64/hex/bin)
   * @return bool
   */
  public function verify($data, $sign, $code = 'base64')
  {
    $ret = false;
    $sign = $this->_decode($sign, $code);
    if ($sign !== false) {
      switch (openssl_verify($data, $sign, $this->pubKey)) {
        case 1:
          $ret = true;
          break;
        case 0:
        case -1:
        default:
          $ret = false;
      }
    }
    return $ret;
  } 

  /**
   * 加密
   *
   * @param string 明文
   * @param string 密文编码(base64/hex/bin)
   * @param int 填充方式(貌似php有bug,所以目前仅支持OPENSSL_PKCS1_PADDING)
   * @return string 密文
   */
  public function encrypt($data, $code = 'base64', $padding = OPENSSL_PKCS1_PADDING)
  {
    $ret = false;
    if (!$this->_checkPadding($padding, 'en')) $this->_error('padding error');
    if (openssl_public_encrypt($data, $result, $this->pubKey, $padding)) {
      $ret = $this->_encode($result, $code);
    }
    return $ret;
  } 

  /**
   * 解密
   *
   * @param string 密文
   * @param string 密文编码(base64/hex/bin)
   * @param int 填充方式(OPENSSL_PKCS1_PADDING / OPENSSL_NO_PADDING)
   * @param bool 是否翻转明文(When passing Microsoft CryptoAPI-generated RSA cyphertext, revert the bytes in the block)
   * @return string 明文
   */
  public function decrypt($data, $code = 'base64', $padding = OPENSSL_PKCS1_PADDING, $rev = false)
  {
    $ret = false;
    $data = $this->_decode($data, $code);
    if (!$this->_checkPadding($padding, 'de')) $this->_error('padding error');
    if ($data !== false) {
      if (openssl_private_decrypt($data, $result, $this->priKey, $padding)) {
        $ret = $rev ? rtrim(strrev($result), "\0") : '' . $result;
      }
    }
    return $ret;
  }
} 

此为具体的RSA类

<?php
/**
 * Author: Wei ZhiHua
 * Date: 2017/6/30 0030
 * Time: 上午 10:15
 */
header('Content-Type:text/html;Charset=utf-8;');
include "RSA.php";
echo '<pre>'; 

$pubfile = 'D:\WWW\test\rsa_public_key.pem';
$prifile = 'D:\WWW\test\rsa_private_key.pem';
$rsa = new RSA($pubfile, $prifile);
$rst = array(
  'ret' => 200,
  'code' => 1,
  'data' => array(1, 2, 3, 4, 5, 6),
  'msg' => "success",
);
$ex = json_encode($rst);
//加密
$ret_e = $rsa->encrypt($ex);
//解密
$ret_d = $rsa->decrypt($ret_e);
echo $ret_e;
echo '<pre>';
echo $ret_d;
echo '<pre>';
$a = 'test';
//签名
$x = $rsa->sign($a);
//验证
$y = $rsa->verify($a, $x);
var_dump($x, $y);
exit; 

您可能感兴趣的文章:

  • PHP检测接口Traversable用法详解
  • PHP实现的MD5结合RSA签名算法实例
  • PHP实现RSA签名生成订单功能【支付宝示例】
  • php rsa 加密,解密,签名,验签详解
  • Golang加密解密之RSA(附带php)
  • php基于openssl的rsa加密解密示例
  • PHP rsa加密解密使用方法
  • php实现RSA加密类实例
  • php rsa加密解密使用详解
  • PHP+JS+rsa数据加密传输实现代码
(0)

相关推荐

  • php rsa 加密,解密,签名,验签详解

    php rsa 加密,解密,签名,验签 由于对接第三方机构使用的是Java版本的rsa加解密方法,所有刚开始在网上搜到很多PHP版本的rsa加解密,但是对接java大多都不适用. 以下php版本是适用于对接java接口,java适用密钥再php语言使用是需要添加 -----BEGIN CERTIFICATE----- -----END CERTIFICATE----- 使用密钥: 加密公钥  public_key.cer 解密私钥  private_key.key 签名私钥 sign_key.k

  • Golang加密解密之RSA(附带php)

    RSA加密算法简史 RSA是1977年由罗纳德·李维斯特(Ron Rivest).阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的.当时他们三人都在麻省理工学院工作.RSA就是他们三人姓氏开头字母拼在一起组成的. RSA加密算法原理 学过算法的朋友都知道,计算机中的算法其实就是数学运算.所以,再讲解RSA加密算法之前,有必要了解一下一些必备的数学知识.我们就从数学知识开始讲解. 必备数学知识 RSA加密算法中,只用到素数.互质数.指数运算.模运算等

  • PHP实现的MD5结合RSA签名算法实例

    本文实例讲述了PHP实现的MD5结合RSA签名算法.分享给大家供大家参考,具体如下: <?php class Md5RSA{ /** * 利用约定数据和私钥生成数字签名 * @param $data 待签数据 * @return String 返回签名 */ public function sign($data='') { if (empty($data)) { return False; } $private_key = file_get_contents(dirname(__FILE__).

  • PHP+JS+rsa数据加密传输实现代码

    JS端代码: 复制代码 代码如下: //文件base64.js: var b64map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; var b64pad="="; function hex2b64(h) { var i; var c; var ret = ""; for(i = 0; i+3 <= h.length; i+=3) { c = pars

  • PHP检测接口Traversable用法详解

    本文实例讲述了PHP检测接口Traversable用法.分享给大家供大家参考,具体如下: Traversable用于检测一个类是否可以使用 foreach 进行遍历,这是一个无法在 PHP 脚本中实现的内部引擎接口,实际编程中我们使用Iterator接口或者IteratorAggregate接口来实现遍历. 接口摘要: Traversable { } Traversable 重要的一个用处就是判断一个类是否可以遍历,下面是官方例子: <?php if( !is_array( $items ) &am

  • php rsa加密解密使用详解

    1.加密解密的第一步是生成公钥.私钥对,私钥加密的内容能通过公钥解密(反过来亦可以) 下载开源RSA密钥生成工具openssl(通常Linux系统都自带该程序),解压缩至独立的文件夹,进入其中的bin目录,执行以下命令: 复制代码 代码如下: openssl genrsa -out rsa_private_key.pem 1024 openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt -out

  • php实现RSA加密类实例

    本文实例讲述了php实现RSA加密类.分享给大家供大家参考.具体分析如下: 通过openssl实现的签名.验签.非对称加解密,需要配合x.509证书(如crt和pem)文件使用. 由于各种原因,该类并不十分完善,欢迎各种测试! <?php /** * RSA算法类 * 签名及密文编码:base64字符串/十六进制字符串/二进制字符串流 * 填充方式: PKCS1Padding(加解密)/NOPadding(解密) * * Notice:Only accepts a single block. B

  • php基于openssl的rsa加密解密示例

    本文实例讲述了php基于openssl的rsa加密解密.分享给大家供大家参考,具体如下: <?php $config = array( //"config" =>"D:/phpserver/Lighttpd/openssl.cnf", //'config' =>'D:/phpStudy/Lighttpd/OpenSSL.cnf', 'private_key_bits' => 1024, // Size of Key. 'private_key

  • PHP实现RSA签名生成订单功能【支付宝示例】

    本文实例讲述了PHP实现RSA签名生成订单功能.分享给大家供大家参考,具体如下: //组合签名 $a=time(); $b=substr($a, 1); //生成随机订单号 $orderid= $b.mt_rand(10000,99999); //合作身份者id,以2088开头的16位纯数字 $mygoods['partner']="2088011744308664"; //商家账号 $mygoods['seller']="2088011744308664"; //

  • PHP rsa加密解密使用方法

    php服务端与客户端交互.提供开放api时,通常需要对敏感的部分api数据传输进行数据加密,这时候rsa非对称加密就能派上用处了,下面通过一个例子来说明如何用php来实现数据的加密解密 1.加密解密的第一步是生成公钥.私钥对,私钥加密的内容能通过公钥解密(反过来亦可以) 下载开源RSA密钥生成工具openssl(通常Linux系统都自带该程序),解压缩至独立的文件夹,进入其中的bin目录,执行以下命令: openssl genrsa -out rsa_private_key.pem 1024 o

随机推荐