php实现RSA加密类实例


Posted in PHP onMarch 26, 2015

本文实例讲述了php实现RSA加密类。分享给大家供大家参考。具体分析如下:

通过openssl实现的签名、验签、非对称加解密,需要配合x.509证书(如crt和pem)文件使用。
由于各种原因,该类并不十分完善,欢迎各种测试!

<?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: linvo
 * @version: 1.0.0
 * @date: 2013/1/23
 */ 
class RSA{ 
 private $pubKey = null; 
 private $priKey = null; 
 /**
  * 自定义错误处理
  */ 
 private function _error($msg){ 
  die('RSA Error:' . $msg); //TODO 
 } 
 /**
  * 构造函数
  *
  * @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); 
  } 
 } 
 /**
  * 生成签名
  *
  * @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; 
 } 
 // 私有方法 
 /**
  * 检测填充类型
  * 加密只支持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; 
 } 
}

测试demo:

<?php 
header('Content-Type:text/html;Charset=utf-8;'); 
include "rsa.php"; 
echo '<pre>'; 
$a = isset($_GET['a']) ? $_GET['a'] : '测试123'; 
////////////////////////////////////// 
$pubfile = 'E:\ssl\cert\pwd.crt'; 
$prifile = 'E:\ssl\cert\pwd.pem'; 
$m = new RSA($pubfile, $prifile); 
$x = $m->sign($a); 
$y = $m->verify($a, $x); 
var_dump($x, $y); 
$x = $m->encrypt($a); 
$y = $m->decrypt($x); 
var_dump($x, $y);

希望本文所述对大家的php程序设计有所帮助。

PHP 相关文章推荐
PHP4之真OO
Oct 09 PHP
测试您的 PHP 水平的题目
May 30 PHP
php URL验证正则表达式
Jul 19 PHP
php ZipArchive压缩函数详解实例
Nov 06 PHP
测试php函数的方法
Nov 13 PHP
PHP生成图片验证码、点击切换实例
Jun 25 PHP
PHP引用的调用方法分析
Apr 25 PHP
tp5框架使用composer实现日志记录功能示例
Jan 10 PHP
PHP simplexml_load_file()函数讲解
Feb 03 PHP
php高性能日志系统 seaslog 的安装与使用方法分析
Feb 29 PHP
TP5框架model常见操作示例小结【增删改查、聚合、时间戳、软删除等】
Apr 05 PHP
php使用Swoole实现毫秒级定时任务的方法
Sep 04 PHP
PHP中实现crontab代码分享
Mar 26 #PHP
PHP利用hash冲突漏洞进行DDoS攻击的方法分析
Mar 26 #PHP
ThinkPHP、ZF2、Yaf、Laravel框架路由大比拼
Mar 25 #PHP
CentOS 安装 PHP5.5+Redis+XDebug+Nginx+MySQL全纪录
Mar 25 #PHP
MacOS 安装 PHP的图片裁剪扩展Tclip
Mar 25 #PHP
php编写的一个E-mail验证类
Mar 25 #PHP
php取得字符串首字母的方法
Mar 25 #PHP
You might like
使用XDebug调试及单元测试覆盖率分析
2011/01/27 PHP
Codeigniter购物车类不能添加中文的解决方法
2014/11/29 PHP
php封装的smartyBC类完整实例
2016/10/19 PHP
thinkPHP+LayUI 流加载实现功能
2019/09/27 PHP
驱动事件的addEvent.js代码
2007/03/27 Javascript
解决jquery .ajax 在IE下卡死问题的解决方法
2009/10/26 Javascript
javascript 打开页面window.location和window.open的区别
2010/03/17 Javascript
JavaScript 格式字符串的应用
2010/03/29 Javascript
时间戳转换为时间 年月日时间的JS函数
2013/08/19 Javascript
原生javascript实现图片弹窗交互效果
2015/01/12 Javascript
浅析Javascript ES6新增值比较函数Object.is
2016/08/24 Javascript
12 款 JS 代码测试必备工具(翻译)
2016/12/13 Javascript
Bootstrap表单制作代码
2017/03/17 Javascript
Vue中建立全局引用或者全局命令的方法
2017/08/21 Javascript
vue进行图片的预加载watch用法实例讲解
2018/02/07 Javascript
Vue基于vuex、axios拦截器实现loading效果及axios的安装配置
2019/04/26 Javascript
redux.js详解及基本使用
2019/05/24 Javascript
NUXT SSR初级入门笔记(小结)
2019/12/16 Javascript
vue实现公共方法抽离
2020/07/31 Javascript
python字符串连接方式汇总
2014/08/21 Python
python根据文件大小打log日志
2014/10/09 Python
python 修改本地网络配置的方法
2019/08/14 Python
Python3.9新特性详解
2020/10/10 Python
多个版本的python共存时使用pip的正确做法
2020/10/26 Python
解决CSS3 transition-delay 属性默认值0不带单位失效的问题
2020/10/29 HTML / CSS
HTML5探秘:用requestAnimationFrame优化Web动画
2018/06/03 HTML / CSS
SteelSeries赛睿官网:游戏外设和配件的领先制造商(耳机、键盘、鼠标和鼠标垫)
2018/06/17 全球购物
巴西服装和鞋子购物网站:Marisa
2018/10/25 全球购物
品质主管的岗位职责
2013/12/04 职场文书
2014年单位植树节活动方案
2014/03/23 职场文书
房屋出售协议书
2014/04/10 职场文书
安全生产工作汇报材料
2014/10/28 职场文书
旷工检讨书1000字
2015/01/01 职场文书
2015年行风建设工作总结
2015/05/15 职场文书
2015年乡镇安全生产工作总结
2015/05/19 职场文书
详解Node.js如何处理ES6模块
2021/05/15 Javascript